Convert Endianness and g ++ warnings

I have the following C ++ code:

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

What work was tested (without the attributes used). When compiling, I get the following errors from g ++ (version 4.4.1)

 || g++ -Wall -Wextra -O3 -ot 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' 

I tried using the following code:

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

but it is interrupted when optimization is enabled due to the punning type.

So why is my used attribute ignored? Is there a workaround for converting endianness (I rely on enumeration to avoid type customization) in templates?

+2
source share
1 answer

I only have gcc 4.2.1, but if I get rid of the attribute ((used)) and give the union a name that it compiles without warning to me.

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

From what I read, the "union" method works on gcc, but is not guaranteed by the standard, the other reinterpret_cast method is incorrect (due to type aliases). However, I think this applies to C, not sure about C ++. Hope this helps.

+2
source

Source: https://habr.com/ru/post/1307428/


All Articles