试图确保我做对了。 在SO上我遇到了一个问题的答案:如何在int中存储字符:
unsigned int final = 0;
final |= ( data[0] << 24 );
final |= ( data[1] << 16 );
final |= ( data[2] << 8 );
final |= ( data[3] );
但是对我的理解这是错的不是吗?
为什么:说data
以小端方式存储整数(例如data[0]=LSB_ofSomeInt)
。
然后如果执行上面代码的机器是小端,final
将保持正确的值,
否则,如果运行在代码上方的机器是大端,它将保持错误的值,不是吗?
试图确保我做对了,我现在不打算在这方面提出更多问题。
答案 0 :(得分:3)
如果您拥有htonl等功能,请不要这样做。
摆脱麻烦
答案 1 :(得分:1)
此代码不依赖于平台的字节顺序:data[0]
始终存储为int
的最重要字节,其余为data[3]
,data
始终为最不重要的字节。
这是“正确”还是“错误”取决于整数在data
数组本身中的编码方式。
但是有一个问题:如果使用char
而不是unsigned char
宣布data[i]
,则签名的int
将首先提升为签名{{1}}并且你最终设置了比你想象的更多的位。
答案 2 :(得分:1)
在小端和大端系统中这是错误的。
如果data
元素的类型为char
,则您需要在执行按位左移之前将所有data
元素强制转换为unsigned char
,否则您可能会遇到符号扩展在具有负值的data
元素上。 char
的签名是实现定义的,char
可以是签名类型。
data[0] << 24
(或甚至(unsigned char) data[0] << 24
)如果data[0]
为负值,则会调用未定义的行为,因为结果值无法在int
中表示,因此您我需要额外投射到unsigned int
。
最好是为unsigned char
声明data
数组,然后在左移之前将每个data
元素投放到unsigned int
。
现在假设您正确地投射它,只有当data[0]
保存您值的最重要字节时,这才有效。
答案 3 :(得分:0)
除了平台特定字节排序的明显问题(其他答案已经解决),你应该小心推广数据类型。
我假设data
是unsigned char
类型的数组。在这种情况下,表达式
data[0] << 24
为零;你刚刚离开了一个8位操作数24位!我没有编译它来检查或查看类型提升规则,但我相信,你把括号括起来的方式,
data[0] << 24
仍为unsigned char
。当你按位时或者使用final
得到结果时它会被提升。充其量,它在解释上留下了太多的东西。更安全,更明确的方法是逐位或先行,然后转移:
final |= data[0]; final <<= 8;
final |= data[1]; final <<= 8;
final |= data[2]; final <<= 8;
final |= data[3]; final <<= 8;
或者您可以明确宣传然后转移:
final |= ((unsigned int)data[0]) << 24;
final |= ((unsigned int)data[1]) << 16;
final |= ((unsigned int)data[2]) << 8;
final |= ((unsigned int)data[3]);
当然,这根本不涉及字节序问题。但这可能是也可能不是问题,取决于data
的来源。