Home > Net >  Operator "<<= " : What does it it mean?
Operator "<<= " : What does it it mean?

Time:11-05

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, since char could be an 8 bit signed type. See Is char signed or unsigned by default?. In which case 0xAB will get translated to a negative number in an implementation-defined way. Avoid this bug by always using uint8_t when dealing with raw binary bytes.

  • c<<2 is subject to Implicit type promotion rules - specifically c will get promoted to a signed int. If the previous issue occured where your char got a negative value, c now holds a negative int.

  • Left-shifting negative values in C invokes undefined behavior - it is always a bug. Shifting signed operands in general is almost never correct.

  • %x isn't a suitable format specifier to print the int you ended up with, nor is it suitable for char.

As for how to fix the code, it depends on what you wish to achieve. It's recommended to cast to uint32 before shifting.

  • Related