I need help solving this problem in my mind, so if anyone had a similar problem it would help me.
Here's my code:
char c=0xAB;
printf("01:%x\n", c<<2);
printf("02:%x\n", c<<=2);
printf("03:%x\n", c<<=2);
Why the program prints:
01:fffffeac
02:ffffffac
03:ffffffb0
What I expected to print, that is, what I got on paper is:
01:fffffeac
02:fffffeac
03:fffffab0
I obviously realized I didn't know what the operator <<= was doing, I thought c = c << 2.
If anyone can clarify this, I would be grateful.
CodePudding user response:
You're correct in thinking that
c <<= 2
is equivalent to
c = c << 2
But you have to remember that c is a single byte (on almost all systems), it can only contain eight bits, while a value like 0xeac requires 12 bits.
When the value 0xeac is assigned back to c then the value will be truncated and the top bits will simply be ignored, leaving you with 0xac (which when promoted to an int becomes 0xffffffac).
CodePudding user response:
<<= means shift and assign. It's the compound assignment version of c = c << 2;.
There's several problems here:
char c=0xAB;is not guaranteed to give a positive result, sincecharcould be an 8 bit signed type. See Is char signed or unsigned by default?. In which case0xABwill get translated to a negative number in an implementation-defined way. Avoid this bug by always usinguint8_twhen dealing with raw binary bytes.c<<2is subject to Implicit type promotion rules - specificallycwill get promoted to a signedint. If the previous issue occured where yourchargot a negative value,cnow holds a negativeint.Left-shifting negative values in C invokes undefined behavior - it is always a bug. Shifting signed operands in general is almost never correct.
%xisn't a suitable format specifier to print theintyou ended up with, nor is it suitable forchar.
As for how to fix the code, it depends on what you wish to achieve. It's recommended to cast to uint32 before shifting.
