如何解决用于字节序测试和字节交换的Union hack
| 对于联合,写入一个成员并从另一个成员读取(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
}
片段1是合法的C或C ++,但不是片段2。我正确吗?可以有人指向标准部分,说可以写联合成员并从另一个成员(即char数组)读取是可以的。
解决方法
我相信从技术上来说,它是不允许的(代码段1),但是大多数编译器仍然允许它,因为人们使用了这种代码。 GCC甚至证明它受支持。
在sizeof(int)== 1的某些机器上,以及在既不是大端也不是小端的某些机器上,您将遇到问题。
可以使用将单词更改为正确顺序的可用功能,也可以使用配置宏进行设置。无论如何,您可能需要识别编译器和OS。
, 有一种非常简单的方法可以解决未定义的行为(几乎每个编译器都定义了未定义的行为;)。
uint32_t i = 0x12345678;
char ch[4];
memcpy( ch,&i,4 );
bool bLittleEndian = ch[0] == 0x78;
这样做的好处是,几乎所有的编译器都会看到,您正在对一定数量的字节进行memcpypy处理并完全优化了memcpy,从而得到与代码段1完全相同的代码,同时完全遵守规则!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。