The traps of a shift in C
The literal 1 is a signed int, so 1 << 31 overflows it and the standard leaves the result undefined.
Write 1u to make the literal unsigned.
C also leaves a shift by the width of the type undefined, and it gives no 0.
A right shift of a negative value keeps the sign on every common compiler.
Try shift traps in the bit editor
Bit 31, which needs 1u in C. Edit the expression or select a bit to flip it.
- value
- 2147483648
Shift traps step by step
Build a mask for bit 31 without the trap:
- Write 1u rather than 1, which makes the literal unsigned.
- Shift it: 1u << 31 gives 0x80000000.
- For a 64-bit register write 1ull << 63.
- The editor above holds the value as a whole number, so it shows the result C leaves undefined.
The literal to use for each width
| Register width | Mask for the top bit | Literal |
|---|---|---|
| 8 | 1u << 7 | 0x80 |
| 16 | 1u << 15 | 0x8000 |
| 32 | 1u << 31 | 0x80000000 |
| 64 | 1ull << 63 | 0x8000000000000000 |
Where shift traps is used
A mask for the top bit of a 32-bit register is the most common place this appears.
A shift amount that comes from a variable can pass the width at run time and never at test time.
A compiler with optimisation on folds undefined behaviour into results that look unrelated.
Shift traps: points to note
- The value 1 << 31 works on many compilers and stays undefined. The next release changes it silently.
- C leaves a shift of a 32-bit value by 32 undefined, and it gives no 0. Guard the amount first.
- A right shift of -8 by 1 gives -4, not a division on the raw bits. Use an unsigned type for a mask.
- Beetwise holds every value as a whole number of unlimited size, so it shows what C leaves undefined.
The full bit editor
The full editor holds many values, evaluates expressions across them, and reads live values from a serial port.
Open this value in the full editorQuestions about shift traps
- Why does C leave 1 << 31 undefined?
- The literal 1 is a signed int of 32 bits. The shift moves a 1 into the sign bit and overflows it.
- What do I write instead?
- Write 1u << 31 for a 32-bit mask, and 1ull << 63 for a 64-bit mask.
- What does a shift by 32 give?
- The standard leaves it undefined. A common result keeps the value, rather than 0.