2010-04-19 82 views
2

我有下面的C++代码:字节顺序转换和g ++警告

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]); 
    } 
}; 

哪些工作,并已经过测试(不使用的属性)。当编译我获得克以下错误+(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' 

我试着用下面的代码:

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); 
    } 
}; 

但能够优化时,它打破由于类型双关语。

那么,为什么我的used属性被忽略? 是否有一个解决方案来转换模板中的字节顺序(我依靠enum来避免类型双关)?

+0

'__attribute__((used))'适用于函数而不是变量/结构体成员(AFAIK)。另外,struct EndianInverser <4, valType>中的'4'是什么? – 2010-04-19 12:48:23

+0

那么4是valType的大小(我想为整数和浮点数使用相同的代码)。我以前使用它来专门化uppon元素大小。 gcc的文档说,使用适用于变量(http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Variable-Attributes.html#Variable-Attributes),所以我在这里有点失落: -/ – 2010-04-19 13:18:20

+0

的确,我依赖于我的记忆和编译器的老版本(4.1.2!)。我有点困惑,为什么这个属性是需要的,因为outVal和v是明确使用的,为什么编译器说他们不是。最后一件事,如果你在你的第二个代码段中将val转换为char *,并且交换字节,这是否有效? – 2010-04-19 14:41:15

回答

2

我只有gcc 4.2.1,但如果我摆脱了属性((已用)),并给联合会一个名字,它会在没有警告的情况下进行编译。

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; 
    } 

从我读过的“联盟”技术适用于海湾合作委员会,但在标准不能保证,其他“的reinterpret_cast”的方法是错误的(因为类型走样)。但我认为这适用于C,不确定C++。希望有所帮助。

+0

非常感谢 – 2010-04-19 20:16:16