左移运算符是否取决于寄存器的大小?

时间:2019-06-23 12:34:31

标签: c 8-bit

让uint8和uint16为8位和16位正整数的数据类型。

uint8 a = 1;
uint16 b = a << 8;

我在32Bit架构上对该程序进行了测试,结果是

  

b = 256

在具有8位长度的寄存器的系统上使用相同的程序会产生结果:

  

b = 0吗?

因为寄存器中的所有位都被<< << 8移位为0?

2 个答案:

答案 0 :(得分:3)

注册无关。这与您的类型的宽度有关。

当您将值移位比其拥有的位数更多时,该行为是不确定的。编译器,程序,计算机,税务局可以相应地合法证明任何结果。而且,不,that's not just theoretical

但是,operands in C are promoted before interesting things are done on them。因此,您的uint8_t在左移之前就变成了int

现在发生什么情况取决于您的体系结构(由编译器配置决定):实现中的int仅8位吗? No, it's not! 然后,结果(无论“寄存器大小”如何)都必须遵守语言规则,并得出数学上适当的答案(256)。而且,即使是这样,您会碰到这种未定义的行为,所以问题就没有意义了。

在引擎盖下,如果需要一个以上的寄存器来保存一个变量,那么这将是并且必须发生的(无论隐含的性能成本如何)。那就是如果根本不使用寄存器。请记住,您是在抽象中编程,而不是手工制作机器代码。您显示的程序片段可以在编译过程中完全优化,完全不需要任何运行时指令。

答案 1 :(得分:2)

  

在具有8位长的寄存器的系统上,同一程序的结果是否为b=0

否。

在表达式a << 8中,变量a将在移位之前被提升int。并且保证int至少为16位。

b在所有平台上的值为256,除非编译器中有错误。

但是,如果将第二行更改为uint32 b = a << 16;,则可能会得到奇怪的结果。 a仍将升级为int,但是如果int为两个字节长,则a << 16将调用未定义的行为。