右移g++时出现意外结果
Unexpected result from shift right g++
我发现将uint64_t值右移64位或更多时会出现异常结果。我本来希望下面的代码输出值0,但它没有输出值>>2,而是只输出g++。
#include <iostream>
#include <cstdint>
using namespace std;
int main(void)
{
uint64_t value = 0x5d4d629e80d5489UL;
int shift = 66;
cout << hex << (value >> shift) << endl;
return 0;
}
我编译并运行:
$ g++ -std=c++0x mad.cpp
$ ./a.out
175358a7a035522
$ uname -a
Linux svr 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
我在另一个g++(Debian 4.4.5-8)4.4.5的Linux盒子上得到了同样的行为。然而,当我用Visual Studio C++(速成版)编译它时,我不会得到同样的行为——我得到了我最初期望的结果——即0。
我想知道,当x和y是序数,y大于x中的位数时,假设C++中的x>>y应该产生0是否安全。这是一个g++错误,还是Visual C++不符合要求?我认为这不是/不应该是未定义的行为?这可能是特定于CPU的吗?
我意识到,我总是可以明确检查每一个超过8*sizeof(value)的移位,但这引入了一个我希望在一些性能关键代码中避免的额外分支。
这是一个已知的问题吗?如果是,为了实现一致的跨平台评估,建议采取什么策略?
根据C++标准关于轮班操作员:
如果右操作数是大于或等于提升的左操作数的长度(以位为单位)。
此行为未定义
考虑一些关于过多比特移位是如何畸形的以及如何保护自己免受其影响的读物:INT34-C。请勿移位负数或超过操作数中存在的位数
未定义行为的一个原因是它取决于底层硬件,后者以不同的方式实现转换。
在最初的8086上,按照要求的次数执行移位,每个位置使用一个时钟刻度。很快人们发现,这导致保证的中断响应时间非常糟糕。
因此,从286开始,硬件屏蔽移位计数,只使用低位。这就是当66变成2位移位时所看到的。
相关文章:
- 尝试将字符串/字符转换为整数会产生意外结果
- RapidXML - 代码创建意外结果
- 类中静态函数C++意外结果
- 指针数组中的意外结果
- 使用指针访问数组元素时出现意外结果
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- C++:比较运算符>和字符串文本的意外结果
- 具有意外结果的 C++ 闭包
- yaml-cpp 比较的意外结果
- 每次都出现意外结果
- 在 Qt 中解析嵌套的 JSON 时出现意外结果(数组不存在)
- 如何避免 std::abs 的意外结果?
- 使用嵌套 if 语句的意外结果
- A ^= B ^= A ^= B;C# Visual Studio 中的意外结果
- 逻辑错误,我将获得意外结果
- 在 c++ 中使用异步的意外结果
- 从函数的返回值将元素C++存储到 std::vector 中时出现意外结果
- 执行递增和递减时"cout"链接会产生意外结果
- OpenCL - 内核方法返回意外结果
- C++使用 std::get_time 解析 YYMMDD ISO 8601 日期字符串会得到意外结果