Skip to content

Shift Left

Level: 201 · for anyone with a hex editor open

One line: X[i] <<= Operand moves each value's bits toward its top by the operand, brings zeros in at the bottom and drops whatever passes the top — so Shift Left 1 is Multiply 2, the signed and unsigned readings write the same bytes, and on a little-endian Short the bits cross from the first byte into the second.

What the dialog does

The manual writes Shift Left as X[i] <<= Operand (Hex Operations), where the operand is a count of bit positions. The bits move within the value, and "the top of the value" is the top of whatever Treat Data As says one value is: the eighth bit of a byte, the sixteenth of a Short. Bits that pass it are gone. Block Shift Left is the variant where they move into the next value instead, and Rotate Left the one where they come back.

In Python

Verified output of shift_left_py.py — regenerated by tools/run_examples.py, never hand-typed.

1. THE TOP BIT FALLS OFF
------------------------------------------------------------------------
   81 is 1000 0001. Shift Left, as Unsigned Byte:

     81 << 1   02   00000010
     81 << 4   10   00010000
     81 << 7   80   10000000

   The low 1 walks up one place per count. The high 1 went past the top
   on the first step and nothing remembers it.

2. SHIFT LEFT 1 IS MULTIPLY 2, AND ADDING THE VALUE TO ITSELF
------------------------------------------------------------------------
     all 256 bytes, the three agree                         True
     Signed and Unsigned write the same, counts 0-7         True

3. ON A LITTLE-ENDIAN SHORT THE BITS CROSS RIGHTWARD ON SCREEN
------------------------------------------------------------------------
   0x1234 << 4 is 0x2340 whichever way the bytes are stored:

     Unsigned Short, big     12 34 -> 23 40
     Unsigned Short, little  34 12 -> 40 23

   In the big-endian row the digits moved left, the way they would on
   paper. In the little-endian row the high byte is the second one, so
   the 3 that left the first byte arrived in the second.

4. A SHIFT BY THE WIDTH OR MORE
------------------------------------------------------------------------
     81 << 7   80
     81 << 8   00
     81 << 9   00

   This program keeps the low eight bits of the true result, so from 8
   on every bit has gone. That is Python's arithmetic, not a rule: C
   leaves a shift by the width or more undefined, Rust's wrapping_shl
   takes the count modulo the width, and the manual does not say what
   the dialog does.

The top bit falls off

Section 1 shifts 81, which is 1000 0001. The low 1 walks up one place per count; the high 1 passes the top on the first step, and 81 << 1 is 02. Section 2 checks that Shift Left 1 writes what Multiply 2 writes, and what adding a value to itself writes, for all 256 bytes, and that the signed and unsigned readings give the same bytes for every count from 0 to 7: a left shift only moves bits, and the sign is a reading of them.

That last check is also why a left shift can change a value's sign without any overflow being reported. 40 shifted left by 1 is 80: +64 read as a Signed Byte before, −128 after.

The bits cross rightward on a little-endian Short

Section 3 shifts 0x1234 left by 4 stored both ways, and both results are 0x2340. In the big-endian row, 12 34 becomes 23 40, and the digits moved left as they would on paper. In the little-endian row, 34 12 becomes 40 23: the high byte is the second one, so the 3 that left the top of the first byte arrived at the bottom of the second — rightward across the screen. The bytes do not say which end is why the same shift can look like it moves in opposite directions.

A shift by the width or more

Section 4 shifts 81 by 7, 8 and 9. The program keeps the low eight bits of the true result, so from 8 on nothing is left. That is a choice, not a rule: C leaves a shift by the width or more undefined, Rust's wrapping_shl takes the count modulo the width — so 0x81u8.wrapping_shl(9) shifts by 1 and gives 02, as the chapter's Rust program shows — and the manual does not say which the dialog does.

What the manual does not say

  • What a count of the width of the type or more does.
  • What a negative count does.

If you are coming from Python or ABAP

Python. (b << n) & 0xFF is Shift Left as Unsigned Byte, and the mask is the whole difference from Python's own <<, which never drops a bit: 0x81 << 9 is 66,048. A negative count raises ValueError instead of shifting the other way.

ABAP. (Not machine-checked — CI cannot run ABAP.) ABAP's bit expressions have BIT-NOT, BIT-AND, BIT-XOR and BIT-OR, and nothing that moves a bit ↗, so a left shift of an integer is a multiplication by a power of two. Write the power with ipow( ) rather than **: ** makes the whole expression's calculation type f, floating point, and ipow( ) keeps it an integer. The integer calculation then raises CX_SY_ARITHMETIC_OVERFLOW where the dialog drops the top bits.

Try it

  1. Shift Left 1 a copy of any file as Unsigned Byte and open Tools > Histogram/Entropy: no odd byte value should remain.
  2. Type 34 12 and Shift Left 4 as Unsigned Short under each Endian setting, and trace which hex digit went where.
  3. Type 81 and Shift Left by 8, then by 9, and note what the dialog writes. This page does not know.
  4. Type 40, Shift Left 1 as Signed Byte, and read the Inspector's signed value before and after.

See also