问题
Here's my code:
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned long int x = 0;
// trying to make x = 2,147,483,648
x = 1 << 31;
printf("%lu", x);
}
It's returning that x = 18446744071562067968. I read that unsigned long int should go up to 4,294,967,296, so why can't I use 1 << 32 to set x equal to 2,147,483,648?
回答1:
1 << 31 causes undefined behaviour, if your system has 32-bit ints. The literal 1 is a signed int.
You need to do an unsigned shift instead of a signed shift:
x = 1UL << 31;
I added L so that the code is still correct even on a 16-bit system, and it doesn't hurt to do so.
Informally, shifting a 1 into the sign bit is undefined. The formal text can be found in section 6.5.7/4 of the C11 standard:
The result of
E1 << E2isE1left-shiftedE2bit positions; vacated bits are filled with zeros. [...] IfE1has a signed type and nonnegative value, andE1×2E2is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Your other question, "why can't I use 1 << 32" is covered by that same quote. What about 1UL << 32 ? If your system has 32-bit unsigned long then this would also be undefined according to 6.5.7/3:
[...] If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined
But it would work if your system had 64-bit unsigned long. To avoid having your code break when compiled on a different system (this goal is known as code portability) you could write (uint64_t)1 << 32 (or 1ULL << 32) which is guaranteed to work.
来源:https://stackoverflow.com/questions/35119136/is-unsigned-long-int-correct-for-this-operation