将字符转换为整数正确的方式

时间:2013-10-12 16:51:41

标签: c

试图确保我做对了。 在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 个答案:

答案 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)

除了平台特定字节排序的明显问题(其他答案已经解决),你应该小心推广数据类型。

我假设dataunsigned 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的来源。