3

My goal here is to remove byte-count+1 bits from the left of this 8-bit integer (or as you'd often call it, unsigned char.

Should be simple really, but this bit of code

uint8_t val = 0xC3;
uint8_t byte_count = 2;
uint8_t cc = val << (byte_count+1) >> (byte_count+1);
printf("%X", cc);

Gives me C3 as a result.

While this one

uint8_t val = 0xC3;
uint8_t byte_count = 2;
uint8_t cc = val;
cc <<= (byte_count+1);
cc >>= (byte_count+1);
printf("%X", cc);

Gives me just the 3.

Yes, I've tried putting a bunch of parenthesis around it.
Yes, I've tried casting everything in the expression to uint8_t.

Why does this happen?

TrisT
  • 639
  • 6
  • 19

1 Answers1

3

Promotion.

Upon stumbling on a few keywords, I found promotion and googled it. Found this answer.

Smaller data types will be implicitly promoted to int/unsigned in an expression. This other answer explains it in detail.

Because our initial uint8_t operand is promoted to a higher bit count integer, then shifting it by (in this case) 3 and back will no longer "remove" those bits. This is because they'll no longer be outside the bit boundary in the first shift.

The same of course doesn't happen for the shift assign, you can't convert the left operand as it's an lvalue (meaning it represents memory, which isn't resizable). It also returns an lvalue representing the left operand, so that can't be promoted either.

printf("%d\n", sizeof(
    (uint8_t)2 + (uint8_t)3
));

//Output: 4
TrisT
  • 639
  • 6
  • 19
  • 1
    Re “you can't convert the left operand as it's an lvalue”: The conversion does occur. In `cc <<= (byte_count+1);`, the value of `cc` is promoted to an `int`, then shifted, then converted to a `uint8_t` for assignment. In this case, that gives the same result as if the shift had been done with a `uint8_t`, so it is invisible, but that is what the C standard specifies. – Eric Postpischil Jul 08 '20 at 21:13
  • @EricPostpischil So basically the same as doing ``cc = cc << (byte_count+1)``. That's very nice thank you. Will you edit or should I? – TrisT Jul 09 '20 at 09:38