为什么是0x7FFFFFFFull | (1 << 31)在C++中返回0xFFFFFFFFFFFFFFFF?

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

M.M*_*M.M 7

首先,你的代码没有按你在标题/问题中所做的那样做; 我已经编辑了标题.

问题是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.