首页 > 后端开发 > C++ > 正文

## 为什么右移位运算符在大移位值时会表现出意外行为?

Barbara Streisand
发布: 2024-10-26 06:29:30
原创
523 人浏览过

## Why Does the Right Shift Operator Exhibit Unexpected Behavior with Large Shift Values?

右移运算符的有趣行为

右移运算符 (>>) 在处理较大的右移值时表现出特殊的行为。考虑以下程序:

<code class="c++">#include <iostream>
#include <stdint.h>

int foo(int a, int b)
{
   return a >> b;
}

int bar(uint64_t a, int b)
{
   return a >> b;
}

int main()
{
    std::cout << "foo(1, 32): " << foo(1, 32) << std::endl;
    std::cout << "bar(1, 32): " << bar(1, 32) << std::endl;
    std::cout << "1 >> 32: " << (1 >> 32) << std::endl; //warning
    std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning
}
登录后复制

foo(1, 32) 的预期输出将为 0,但令人惊讶的是,它返回 1。这可以归因于以下原因:

逻辑移位与算术移位

在 x86/x86-64 架构上,右移运算符实际上执行逻辑右移,这意味着它会填充空出的空间带有 0 的位,无论左操作数的符号如何。该行为类似于使用 >>> b.

编译器优化

在 foo(1, 32) 的情况下,值 32 被转换为 int,这实际上被截断为 32 位。由于 int 可以容纳的最大值是 231-1,因此右移本质上是一个 >>> (32 % 32),其计算结果为 0。

未定义的行为

相关的 C 标准规定,对于计数大于的右移,“行为未定义”大于或等于提升的左操作数的宽度。在这种情况下,1>>都成立。 32、(int)1>> (int)32 的计数大于 32,导致不可预测的结果。

与 bar(1, 32) 的区别

函数 bar 采用 64 位无符号整数,保证宽度大于 32。因此,bar 中的右移不受未定义行为的影响。

结论

的行为当处理大的移位值时,右移运算符变得不明确。在 x86/x86-64 架构上,执行逻辑右移,而在 ARM 上,可能会使用不同的实现。由于未定义的行为,在可移植代码中应避免计数大于或等于操作数宽度的右移结果。

以上是## 为什么右移位运算符在大移位值时会表现出意外行为?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!