右移运算符的有趣行为
右移运算符 (>>) 在处理较大的右移值时表现出特殊的行为。考虑以下程序:
#include
#include
int foo(int a, int b)
{
return a >> b;
}
int bar(uint64_t a, int b)
{
return a >> b;
}
int main()
{
std::cout > 32: " > 32) > (int)32: " > (int)32) foo(1, 32) 的预期输出将为 0,但令人惊讶的是,它返回 1。这可以归因于以下内容:
逻辑移位与算术运算Shift
在 x86/x86-64 架构上,右移运算符实际上执行逻辑右移,这意味着它用 0 填充空出的位,而不管左操作数的符号。该行为类似于使用 >>> b.
编译器优化
在 foo(1, 32) 的情况下,值 32 被转换为int,实际上被截断为 32 位。由于 int 可以容纳的最大值为 231-1,因此右移本质上是 >>> (32 % 32),其计算结果为 0。
Undefined行为
相关的 C 标准规定,对于计数大于或等于提升的左操作数宽度的右移,“行为未定义”。在这种情况下,1 >> 32 和 (int)1 >> (int)32 的计数都大于 32,导致不可预测的结果。
与 bar(1, 32)[ 的差异&&&]
函数bar采用64位无符号整数,保证其宽度大于32。因此,bar中的右移不受未定义行为的影响。 结论
处理大移位值时,右移运算符的行为变得不明确。在 x86/x86-64 架构上,执行逻辑右移,而在 ARM 上,可能会使用不同的实现。由于未定义的行为,在可移植代码中应避免计数大于或等于操作数宽度的右移结果。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3