【问题标题】:Are leftshift operators dependent on register size?左移运算符是否依赖于寄存器大小?
【发布时间】:2019-06-23 12:34:31
【问题描述】:

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

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

我在 32 位架构上测试了这个程序,结果

b = 256

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

b = 0 ?

因为寄存器中的所有位都被 移到 0

【问题讨论】:

  • 欢迎来到 Stack Overflow。您将位移动到其大小末端的目标是什么?这似乎有点不寻常,可能是未定义的行为。
  • 行为取决于数据类型的大小。在表达式中使用时,整数操作数被提升为可能更大的整数。提升的大小决定了班次操作的行为。

标签: c 8-bit


【解决方案1】:

寄存器无关紧要。这大约是您的类型的宽度。

当您将一个值移动的位数超过它所拥有的位数时,该行为是未定义的。编译器、程序、计算机、税务局可以相应地合法地显示任何结果。而且,不,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)。 而且,即使是这样,你' d 遇到了未定义的行为,所以这个问题没有实际意义。

在引擎盖下,如果需要多个寄存器来保存一个变量,那么这就是将会发生并且必须发生的事情(无论结果隐含的性能成本如何)。那就是如果使用寄存器完全;请记住,您是在抽象编程,而不是手工编写机器代码。您展示的程序 sn-p 可以在编译期间完全优化掉,并且不需要任何运行时指令根本

【讨论】:

  • intunsigned int 都保证至少为 16 位。
  • 大部分是对的,取模以上两个cmets。
【解决方案2】:

在具有 8 位长度寄存器的系统上,相同的程序会得到b=0吗?

没有。

在表达式a &lt;&lt; 8 中,变量a 将在位移之前提升intint 保证至少为 16 位。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2022-09-25
    • 1970-01-01
    • 2015-12-12
    • 2011-07-03
    • 1970-01-01
    相关资源
    最近更新 更多