When I do (0x7fffffff | 0x8000000) I am getting 0xffffffffffffffff instead of the expected 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. If you have 32-bitint(which apparently you do, judging by the results), this cause arithmetic overflow. In C++14 this is implementation-defined behaviour; prior to C++14 it causes undefined behaviour. Reference.Usually the implementation-defined behaviour will be to generate the int with the sign bit set and the other bits unset. In 2's complement this value is
INT_MIN. You then perform arithmetic between anunsigned long longand anint. This is defined as: theintis converted tounsigned long long.Converting signed integers to unsigned is done by wrapping it around (modular arithmetic) modulo
ULLONG_MAX+1. So the result of(unsigned long long)INT_MINis a very large positive number, in fact0xFFFFFFFF80000000. (To check this, add0x80000000to it to get0).So you are actually doing
0x7FFFFFFF | 0xFFFFFFFF80000000which gives the observed result.Later on it gets worse:
1 << 32and larger causes undefined behaviour due to shifting by the whole width of the type.To fix this, change
0x1in your code to1ull. The you will be shifting anunsigned long long, instead of anint.