[英]Why is 0x7FFFFFFFull | (1 << 31) returning 0xFFFFFFFFFFFFFFFF in C++?
When I do (0x7fffffff | 0x8000000) I am getting 0xffffffffffffffff instead of the expected 0xffffffff. 当我这样做(0x7fffffff | 0x8000000)时,我得到0xffffffffffffffff而不是预期的0xffffffff。 What am I missing?
我错过了什么?
Some sample code and output to illustrate my question. 一些示例代码和输出来说明我的问题。
Code: 码:
#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;
}
Output: 输出:
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
Firstly your code does not do what you say in your title/question; 首先,你的代码没有按你在标题/问题中所做的那样做; I have edited the title.
我已经编辑了标题。
The problem is 1 << 31
. 问题是
1 << 31
。 If you have 32-bit int
(which apparently you do, judging by the results), this cause arithmetic overflow. 如果你有32位
int
(显然你这样做,根据结果判断),这会导致算术溢出。 In C++14 this is implementation-defined behaviour; 在C ++ 14中,这是实现定义的行为; prior to C++14 it causes undefined behaviour.
在C ++ 14之前,它会导致未定义的行为。 Reference .
参考 。
Usually the implementation-defined behaviour will be to generate the int with the sign bit set and the other bits unset. 通常,实现定义的行为是生成符号位设置的int,其他位未设置。 In 2's complement this value is
INT_MIN
. 在2的补码中,该值为
INT_MIN
。 You then perform arithmetic between an unsigned long long
and an int
. 然后,您在
unsigned long long
和int
之间执行算术运算。 This is defined as: the int
is converted to unsigned long long
. 这被定义为:
int
被转换为unsigned long long
。
Converting signed integers to unsigned is done by wrapping it around (modular arithmetic) modulo ULLONG_MAX+1
. 将有符号整数转换为无符号是通过将其包围(模运算)模
ULLONG_MAX+1
。 So the result of (unsigned long long)INT_MIN
is a very large positive number, in fact 0xFFFFFFFF80000000
. 因此
(unsigned long long)INT_MIN
是一个非常大的正数,实际上是0xFFFFFFFF80000000
。 (To check this, add 0x80000000
to it to get 0
). (要检查此项,请向其添加
0x80000000
以获得0
)。
So you are actually doing 0x7FFFFFFF | 0xFFFFFFFF80000000
所以你实际上在做
0x7FFFFFFF | 0xFFFFFFFF80000000
0x7FFFFFFF | 0xFFFFFFFF80000000
which gives the observed result. 0x7FFFFFFF | 0xFFFFFFFF80000000
,它给出了观察到的结果。
Later on it gets worse: 1 << 32
and larger causes undefined behaviour due to shifting by the whole width of the type. 后来它变得更糟:
1 << 32
和更大导致由于移动类型的整个宽度而导致的未定义行为。
To fix this, change 0x1
in your code to 1ull
. 要解决此问题,请将代码中的
0x1
更改为1ull
。 The you will be shifting an unsigned long long
, instead of an int
. 你将转移一个
unsigned long long
,而不是int
。
because of sign extension val
is an unsigned long long. 因为符号扩展
val
是一个unsigned long long。 But val is not what you are shifting. 但是val不是你正在改变的。 You are shifting 0x1, an int, then extending it to long long for the '|='
你正在转移0x1,一个int,然后将它扩展为long'for'| ='
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.