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);
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
.