联盟黑客进行端点测试和字节交换

时间:2011-06-15 14:47:40

标签: c++ c unions

对于联合,写入一个成员并从其他成员读取(char数组除外)是UB。

//snippet 1(testing for endianess): 

union
{
    int  i;
    char c[sizeof(int)];
} x;

x.i = 1;                     // writing to i
if(x.c[0] == 1)              // reading from c[0]
{   printf("little-endian\n");
}
else
{   printf("big-endian\n");
}

//snippet 2(swap bytes using union):

int swapbytes()
{
    union                   // assuming 32bit, sizeof(int)==4
    {        
        int  i;
        char c[sizeof(int)];
    } x;
    x.i = 0x12345678;       // writing to member i
    SWAP(x.ch[0],x.ch[3]);  // writing to char array elements
    SWAP(x.ch[1],x.ch[2]);  // writing to char array elements
    return x.i;             // reading from x.i 
}   

Snippet 1是合法的C或C ++,但不是代码段2.我是否正确?有人可以指向标准部分,它表示可以写入union的成员并从另一个成员读取char数组。

2 个答案:

答案 0 :(得分:3)

有一种非常简单的方法可以解决未定义的行为(在几乎所有编译器中定义的未完成的behvaiour;)。)

uint32_t i = 0x12345678;
char ch[4];
memcpy( ch, &i, 4 );

bool bLittleEndian = ch[0] == 0x78;

这有额外的好处,几乎每个编译器都会看到你正在记忆一个恒定的字节数并完全优化memcpy,从而产生与你的代码片段1完全相同的代码,同时完全符合规则! / p>

答案 1 :(得分:2)

我相信它(代码段1)在技术上允许,但大多数编译器仍然允许它,因为人们使用这种代码。 GCC甚至记录了它的支持。

在某些机器上遇到问题,这些机器的sizeof(int)== 1,有些机器既不是大端也不是小端。

使用可用的功能将单词更改为正确的顺序,或使用配置宏设置此功能。无论如何,您可能需要识别编译器和操作系统。