2010-04-19 4 views
2

J'ai le code C++ suivant:conversion boutisme et g ++ avertissements

template <int isBigEndian, typename val> 
struct EndiannessConv 
{ 
    inline static val fromLittleEndianToHost(val v) 
    { 
     union 
     { 
      val outVal __attribute__ ((used)); 
      uint8_t bytes[ sizeof(val) ] __attribute__ ((used)); 
     } ; 

     outVal = v; 
     std::reverse(&bytes[0], &bytes[ sizeof(val) ]); 

     return outVal; 
    } 

    inline static void convertArray(val v[], uint32_t size) 
    { 
     // TODO : find a way to map the array for (uint32_t i = 0; i < size; i++) 
     for (uint32_t i = 0; i < size; i++) 
      v[i] = fromLittleEndianToHost(v[i]); 
    } 
}; 

Quels travaux et a été testé (sans les attributs utilisés). Lors de la compilation j'obtenir les erreurs suivantes de g ++ (version 4.4.1)

|| g++ -Wall -Wextra -O3 -o t t.cc 
|| t.cc: In static member function 'static val EndiannessConv<isBigEndian, val>::fromLittleEndianToHost(val)': 
t.cc|98| warning: 'used' attribute ignored 
t.cc|99| warning: 'used' attribute ignored 
|| t.cc: In static member function 'static val EndiannessConv<isBigEndian, val>::fromLittleEndianToHost(val) [with int isBigEndian = 1, val = double]': 
t.cc|148| instantiated from here 
t.cc|100| warning: unused variable 'outVal' 
t.cc|100| warning: unused variable 'bytes' 

J'ai essayé d'utiliser le code suivant:

template <int size, typename valType> 
struct EndianInverser { /* should not compile */ }; 

template <typename valType> 
struct EndianInverser<4, valType> 
{ 
    static inline valType reverseEndianness(const valType &val) 
    { 
     uint32_t castedVal = 
      *reinterpret_cast<const uint32_t*>(&val); 
     castedVal = (castedVal & 0x000000FF << (3 * 8)) 
       | (castedVal & 0x0000FF00 << (1 * 8)) 
       | (castedVal & 0x00FF0000 >> (1 * 8)) 
       | (castedVal & 0xFF000000 >> (3 * 8)); 

     return *reinterpret_cast<valType*>(&castedVal); 
    } 
}; 

mais il casse lors de l'activation des optimisations en raison du type calembour . Par conséquent, pourquoi mon attribut used a-t-il été ignoré? Y a-t-il une solution de contournement pour convertir l'endianness (je me fie à l'énumération pour éviter le type de punition) dans les modèles?

+0

'__attribute__ ((utilisé))' s'applique aux fonctions plutôt qu'aux variables/membres de la structure (AFAIK). Aussi, quel est le '4' dans la structure EndianInverser <4, valType>? –

+0

Bien 4 est la taille de valType (je voudrais utiliser le même code pour les entiers et les flottants). Je l'utilise avant pour spécialiser la taille de l'élément uppon. La documentation de gcc dit qu'utilisé s'applique aux variables (http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Variable-Attributes.html#Variable-Attributes), donc je suis un peu perdu ici : -/ –

+0

Certes, je comptais sur ma mémoire et une ancienne version (4.1.2!) Du compilateur. Je suis un peu confus pourquoi l'attribut est nécessaire puisque outVal et v sont clairement utilisés, et pourquoi le compilateur dit qu'ils ne le sont pas. Dernière chose, si vous lancez val pour un char * dans votre deuxième segment de code, et échangez des octets, cela fonctionne-t-il? –

Répondre

2

J'ai seulement gcc 4.2.1 mais si je me débarrasse de l'attribut ((utilisé)) et donne à l'union un nom qu'il compile sans avertissements pour moi.

inline static val fromLittleEndianToHost(val v) 
    { 
     union 
     { 
      val outVal ; 
      uint8_t bytes[ sizeof(val) ] ; 
     } u; 

     u.outVal = v; 
     std::reverse(&u.bytes[0], &u.bytes[ sizeof(val) ]); 

     return u.outVal; 
    } 

D'après ce que j'ai lu la technique du « syndicat » travaille sur gcc mais n'est pas garanti dans la norme, l'autre méthode « reinterpret_cast » est erroné (en raison de l'aliasing de type). Cependant, je pense que cela s'applique à C, pas sûr de C++. J'espère que cela pourra aider.

+0

Merci, ça marche bien –

Questions connexes