Преобразование порядка байтов и предупреждения g ++ - PullRequest
2 голосов
/ 19 апреля 2010

У меня есть следующий код C ++:

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

Какая работа и была проверена (без используемых атрибутов). При компиляции я получаю следующие ошибки от g ++ (версия 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 );
    }
};

но он прерывается при включении оптимизации из-за типа punning.

Итак, почему мой атрибут used был проигнорирован? Есть ли обходной путь для преобразования порядка байтов (я полагаюсь на enum, чтобы избежать наложения типов) в шаблонах?

1 Ответ

2 голосов
/ 19 апреля 2010

У меня есть только 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;
  }

Из того, что я прочитал, метод 'union' работает на gcc, но не гарантируется в стандарте, другой метод 'reinterpret_cast' неправильный (из-за псевдонимов типов). Однако я думаю, что это относится к C, не уверен насчет C ++. Надеюсь, это поможет.

...