red*_*maw 2 c++ bit-manipulation bit-shift bitwise-operators
当我这样做(0x7fffffff | 0x8000000)时,我得到0xffffffffffffffff而不是预期的0xffffffff.我错过了什么?
一些示例代码和输出来说明我的问题.
码:
#include <iostream>
using namespace std;
int main()
{
unsigned long long val = 0;
for (int i = 0; i < 64; i++) {
val |= 0x1 << i;
cout << i << ": " << std::hex << val << std::dec << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0: 1 1: 3 2: 7 3: f 4: 1f 5: 3f 6: 7f 7: ff 8: 1ff 9: 3ff 10: 7ff 11: fff 12: 1fff 13: 3fff 14: 7fff 15: ffff 16: 1ffff 17: 3ffff 18: 7ffff 19: fffff 20: 1fffff 21: 3fffff 22: 7fffff 23: ffffff 24: 1ffffff 25: 3ffffff 26: 7ffffff 27: fffffff 28: 1fffffff 29: 3fffffff 30: 7fffffff 31: ffffffffffffffff 32: ffffffffffffffff 33: ffffffffffffffff 34: ffffffffffffffff 35: ffffffffffffffff 36: ffffffffffffffff 37: ffffffffffffffff 38: ffffffffffffffff 39: ffffffffffffffff 40: ffffffffffffffff 41: ffffffffffffffff 42: ffffffffffffffff 43: ffffffffffffffff 44: ffffffffffffffff 45: ffffffffffffffff 46: ffffffffffffffff 47: ffffffffffffffff 48: ffffffffffffffff 49: ffffffffffffffff 50: ffffffffffffffff 51: ffffffffffffffff 52: ffffffffffffffff 53: ffffffffffffffff 54: ffffffffffffffff 55: ffffffffffffffff 56: ffffffffffffffff 57: ffffffffffffffff 58: ffffffffffffffff 59: ffffffffffffffff 60: ffffffffffffffff 61: ffffffffffffffff 62: ffffffffffffffff 63: ffffffffffffffff
首先,你的代码没有按你在标题/问题中所做的那样做; 我已经编辑了标题.
问题是1 << 31.如果你有32位int(显然你这样做,根据结果判断),这会导致算术溢出.在C++ 14中,这是实现定义的行为; 在C++ 14之前,它会导致未定义的行为.参考.
通常,实现定义的行为是生成符号位设置的int,其他位未设置.在2的补码中,这个值是INT_MIN.然后在a unsigned long long和a 之间执行算术运算int.这被定义为:int被转换为unsigned long long.
将有符号整数转换为无符号整数是通过将其包装(模运算)模数来完成的ULLONG_MAX+1.(unsigned long long)INT_MIN事实上,结果是一个非常大的正数0xFFFFFFFF80000000.(要检查此项,请添加0x80000000到其中0).
所以你实际上在做的0x7FFFFFFF | 0xFFFFFFFF80000000是给出观察到的结果.
稍后它会变得更糟:1 << 32由于移动了整个类型的宽度,更大会导致未定义的行为.
要解决此问题,0x1请将代码更改为1ull.你将改变一个unsigned long long,而不是一个int.