切换字节顺序没有类型惩罚

时间:2017-06-02 00:12:46

标签: c++ c++11 bit-shift type-punning byte-shifting

我需要切换字节顺序,以便int16包含内容(byte1,byte2) - > (byte2,byte1)。我是用工会做的:

union ConversionUnion
{
    uint8_t m_8[4];
    uint16_t m_16[2];
    uint32_t m_32;
};

//use
uint16_t example = 0xFFDE
ConversionUnion converter;
converter.m_16[0] = example;
std::swap(converter.m_8[0], converter.m_8[1]);
example = converter.m_16[0]; //0xDEFF

现在这对gcc有用,但我被告知这是未定义的行为(gcc 6.3,C ++ 11)。

问题:

1)这是不确定的行为,我问,因为我之前已经在嵌入式代码中看到了这一点。其他stackoverflow问题似乎在争论这个问题,实际上是对的(对于C ++ 11和C ++ 14)。

2)如果这是未定义的行为,则可以以便携方式进行字节顺序交换而无需一堆位移。我真的讨厌一点点转移,它非常难看。

3 个答案:

答案 0 :(得分:4)

通过char*允许类型惩罚,那么为什么不使用它而不是联合呢?

uint16_t example = 0xFFDE;
char *char_alias = reinterpret_cast<char*>(&example);
std::swap(char_alias[0], char_alias[1]);

答案 1 :(得分:2)

依赖于未定义的行为或模糊语言(联合)的语义不一定更惯用或更容易阅读。我发现这个循环更容易解析:

uint32_t example = 0xc001c0de;
unsigned char *p = reinterpret_cast<unsigned char*>(&example);

for (size_t low = 0, high = sizeof(example) - 1;
     high > low;
     ++low, --high)
{
    std::swap(p[low], p[high]);
}

答案 2 :(得分:1)

  1. 人们在某种程度上不同意这一点。我想那个

      

    它的未定义行为

    但是我的观点不是一个有价值的补充。

  2. 使用无符号类型进行字节交换很容易(BTW字节交换有符号类型没有意义)。只需提取单个字节并重新排列。在constexpr函数或宏中隐藏丑陋。

    constexpr uint16_t bswap(uint16_t value);
    {
        uint16_t high_byte = (value >> 8) & 0xff;
        uint16_t low_byte = value & 0xff;
        return (low_byte << 8) | high_byte;
    }
    
  3. 顺便说一句,如果你在嵌入式代码中看到某些东西,并且它有效,那么这并不表示它是安全的!嵌入式代码通常牺牲了可移植性以提高效率,有时使用未定义的行为,这是说服特定编译器生成有效代码的唯一方法。

相关问题