Search code examples
chexbit-shiftbyte-shifting

Why does bit shifting with equal sign prints out different result opposed to non-equal case?


Why are 01 and 02 case different?

char c=0xAB;
printf("01:%x\n", c<<2); // fffffeac
printf("02:%x\n", c<<=2); //ffffffac
printf("03:%x\n", c<<=2);

Solution

  • Implicit promotions.

    You are on a system that uses twos complement for representing data in native machine format, char is signed and has 8 bits and int has 32 bits on your machine.

    The c and 2 in c<<2 are implicitly promoted to int, so it becomes (int)c << (int)2. c is 0xAB, (int)c is sign-extended to 32 bits so it is 0xffffffab. Then <<2 happens so the resulting value is 0xfffffeac.

    The c <<= 2 stores the value of 0xfffffeac inside c first, then the value of the whole expression becomes the value of c after the assignment. So the result of c << 2 being (int)0xfffffeac is converted to char on assignment to c. Because char has 8 bits on your machine, the value is truncated to 8 bits and c becomes equal to 0xac. Then again, default argument promotions happen for each argument that is a part of the variable argument list in a variable argument function call, like printf(const char *, ...); - each argument after .. undergoes default argument promotions. So then c now beeing equal to 0xac is again sign-extended to 32 bits to int, so becomes 0xffffffac.