关于c ++:如果计数大于类型的宽度,是右移未定义的行为吗?

Is right shift undefined behavior if the count is larger than the width of the type?

我刚刚检查了C++标准。似乎以下代码不应是未定义的行为:

1
2
3
unsigned int val = 0x0FFFFFFF;
unsigned int res = val >> 34;  // res should be 0 by C++ standard,
                               // but GCC gives warning and res is 67108863

根据标准:

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1
has an unsigned type or if E1 has a signed type and a non-negative
value, the value of the result is the integral part of the quotient of
E1/2^E2. If E1 has a signed type and a negative value, the resulting
value is implementation-de?ned.

根据标准,由于34不是负数,所以变量res为0。

gcc对代码段给出以下警告,res67108863

warning: right shift count >= width of type

我还检查了gcc发出的汇编代码。它只调用SHRL,而shrl的intel指令文档,res不是零。

这是否意味着GCC不在英特尔平台上实现标准行为?


第1段EDOCX1·0移位算子的C++标准草案(强调矿山):

The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

因此,如果unsigned int等于或小于32 bits,那么这是未定义的,这正是gcc向您发出的警告。


要准确解释发生了什么:编译器将把34加载到寄存器中,然后将常量加载到另一个寄存器中,并对这两个寄存器执行右移位操作。x86处理器对移位值执行"移位计数%位",这意味着您将得到2的右移位。

由于0x0fffffff(268435455十进制)除以4=67108863,这就是您看到的结果。

如果你有一个不同的处理器,例如一个PowerPC(我认为),它可能会给你零。