2010-04-19 79 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