Beetwise

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.

31
30
29
28
27
26
25
24
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0x80000000
hex · 32 bits
value
2147483648
Bit width
Shift

Shift traps step by step

Build a mask for bit 31 without the trap:

  1. Write 1u rather than 1, which makes the literal unsigned.
  2. Shift it: 1u << 31 gives 0x80000000.
  3. For a 64-bit register write 1ull << 63.
  4. 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

The literal to use for each width
Register widthMask for the top bitLiteral
81u << 70x80
161u << 150x8000
321u << 310x80000000
641ull << 630x8000000000000000

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 editor

Questions 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.