2

This question is from CSAPP CMU ICS 2015Fall Lecture 02 Bits, Bytes, and Integers 19:30 and the related scripts are

The other thing is confusing to people is

What should happen if you say I want to shift an 8-bit number 8 positions to the left

And x is a single byte what do you think you should get

Zero that would be a pretty logical thing you kind of shift all those bits out you fill them with zeros

----------- I don't understand -----------

On most machines you'll get whatever x was

Because what will do is it will compute this number mod 8

And the reason that happens is if you think about it

It's looking at just the lower two three bits of the shift amount and ignoring all the rest

So that's effectively like module 8

So that's just a warning and some machines it does

What you just thought it should and other machines it does this

And so there's no no guarantee and in C that it will be one way or the other

Randal E. Bryant says there are two results when shifting an 8-bit number 8 positions to the left. (Correct me if I'm wrong)

  1. zero
  2. module 8 unchanged

I place a horizontal rule to separate the part I don't understand. Especially On most machines you'll get whatever x was and Because what will do is it will compute this number mod 8, I don't understand why x is the same with x mod 8.

Could someone explain a bit more on the part below the horizontal rule, better with a runnable program?

There are some related questions on SO like What happens with bitwise shift for all 8 bits and Left shift operation on an unsigned 8 bit integer, but both didn't contain the module part.

Ynjxsjmh
  • 28,441
  • 6
  • 34
  • 52

1 Answers1

2

Shifting an 8-bit byte 8 positions to the left can be analyzed in different ways:

  • Arithmetically, shifting a value 8 positions to the left is a multiplication by 256, which produces a number whose 8 low order bits are all zero, so when stored back into an 8-bit byte, you get 0.
  • Hardware shift instruction typically only shift memory words by a number of bits that is less than their width. On many architectures, such as intel, this shift amount number is obtained by masking the higher order bits of the shift value. So the instruction to shift a byte by 8 positions to the left effectively shifts the value in the 8-bit register or memory argument by 8 & 7 positions, so by 0 bits, leaving the value unchanged.
  • To accommodate for hardware limitations, the C language makes it undefined to shift an integer by a number of positions greater or equal to its width. This applies after the integer promotions, so it does not apply to 8-bit bytes (for example stored in a uint8_t) because these values are first promoted to the type int, which has at least 15 value bits.

So in the C language, shifting a byte by 8 positions multiplies its value by 256, which may eventually exceed the range of type int on architectures with 16-bit ints.

Let's analyze this innocent looking code:

    uint8_t shift8(uint_8 b) {
        return b << 8;
    }

Because b is first promoted to int, preserving its value. This value is multiplied by 256, potentially exceeding the range of int, causing undefined behavior. On architectures with int larger than 16 bits, the value is then implicitly converted to the return type uint8_t, which full defined and evaluated to the value modulo 256, which is of course 0.

So the above function is conformant and always returns 0 on many systems, but it is not fully conformant and has undefined behavior on architectures with 16-bit ints.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Excellent answer, I understand why the value keeps unchanged in hardware shift instruction now. However, I still don't understand why professor Randal E. Bryant says it is effectively like module 8? – Ynjxsjmh Apr 13 '20 at 13:22
  • @Ynjxsjmh: When he says *because it will compute this number mod 8*, he refers to the shift value, not the value to be shifted (look at the blackboard, he points to the right part of `<<`). 8 mod 8 is 0 so the value is not shifted at all. – chqrlie Apr 13 '20 at 13:39