0

只是想确保我做对了。在 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则将保持正确的值,否则如果运行上述代码的机器是大端,它将保持错误的值,不是它?

只是想确保我做对了,我现在不会在这个方向上问更多问题。

4

4 回答 4

3

当你有htonl等函数时不要这样做。

省去麻烦

于 2013-10-12T16:55:32.740 回答
1

此代码不依赖于平台的字节序:data[0]始终存储为 的最高有效字节int,然后是其余字节,并且data[3]始终是最低有效字节。

这是“正确”还是“错误”取决于整数在data数组本身中的编码方式。

但是有一个问题:如果data已使用char而不是声明unsigned char,则已签名data[i]将首先提升为已签名int,并且您最终设置的位数比您预期的要多。

于 2013-10-12T16:55:40.053 回答
1

这在小端和大端系统中都是错误的。

如果data元素是 type char,则需要在进行按位左移之前将所有data元素强制转换为 ,否则您可能会在具有负值的元素上遇到符号扩展。的签名是实现定义的,可以是有符号的类型。unsigned chardatacharchar

如果是负值,也data[0] << 24(或什至(unsigned char) data[0] << 24)将调用未定义的行为,因为结果值无法在 an 中表示,因此您需要对.data[0]intunsigned int

最好的方法是声明一个unsigned char数组data,然后将每个data元素转换unsigned int为左移之前。

现在假设你正确地转换它,这只有在data[0]保存你的值的最重要字节时才有效。

于 2013-10-12T17:01:09.347 回答
0

除了特定于平台的字节顺序的明显问题(其他答案已经解决)之外,您应该小心提升数据类型。

我假设这data是一个 type 数组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

于 2013-10-12T17:13:04.007 回答