将整数左移32位

Ric*_*ich 2 c++

在GCC下,以下代码始终返回<<if 的左操作数num1s == 0

0xFFFFFFFFu << (32-num1s);
Run Code Online (Sandbox Code Playgroud)

读完之后,为什么使用32次以上的整数时,32位整数为何不左移“ <<”?,以及David Heffernan引用的标准,似乎如果左操作数是unsigned,则它是定义的操作。仅当E1(左操作数)具有带符号的类型和非负值时,它才可能导致未定义的行为。

谁能解释标准是否明确指出,如果移位的数量大于该类型包含的位数,则它是未定义的行为

And*_*nov 6

CoryKramer 已经回答了为什么它是标准未定义的行为。

我将尝试解释它在真实情况下是如何工作的。C++ 编译器通常将32 位整数的<<and>>运算符实现为汇编指令,而不检查操作数范围。这意味着结果取决于移位指令的处理器特定实现。

例如,Intel 处理器的 32 位 SHL/SHR/SAL/SAL 指令规范表示:

目标操作数可以是寄存器或内存位置。计数操作数可以是立即数或寄存器CL。计数被屏蔽为 5 位,这将计数范围限制为 0 到 31。

这意味着这a << b将出现a << (b & 0x1f)在英特尔处理器上。所以移位32位就意味着不移位。

但您不应该依赖此信息!编译器还可以优化代码并使用向量指令实现移位运算符。在这种情况下,即使处理器规范也未指定该行为。


Cor*_*mer 5

§5.8移位运算符

结果的类型是提升后的左操作数的类型。如果右操作数为负或大于或等于提升后的左操作数的位长度,则该行为是不确定的。

的值E1 << E2E1左移位的E2位置;空出的位为零。如果E1具有无符号类型,则结果的值E1 × 2E2将为,比结果类型中可表示的最大值减少模。否则,如果E1具有带符号的类型和非负值,并且E1×2E2可以在结果类型中表示,则为结果值;否则,为结果。否则,行为是不确定的。