6

I was a bit messing around with uint8_t and was curious what happens when I outflow bits to the left and found that

uint8_t i = 234;

uint8_t j = (i << 1);
auto    k = (i << 1);

std::cout << (int)j << std::endl;

std::cout << k << std::endl;

prints out

212
468

and not the expected

212
212

It seems like << does promote an uint8_t too some wider integer type. Why does it do this?

Here a link where you see it in action

Ackdari
  • 3,222
  • 1
  • 16
  • 33
  • 2
    It seems you can do hardly anything to a `uint8_t` without having it promoted to `int`. – 500 - Internal Server Error Aug 22 '19 at 12:26
  • 3
    Similar question for [tag:c]: https://stackoverflow.com/questions/11203015/integer-promotion-with-the-operator. I think it would be the same in C++ – Artyer Aug 22 '19 at 12:27
  • Because the standard say so... For some micro controller, you have have an option to disable such promotion for better efficiency (and not be conformant to specifications. – Phil1970 Aug 22 '19 at 12:33
  • @500-InternalServerError I disagree - you can do _more_ with it than you can with an `int`! ;) – Lightness Races in Orbit Aug 22 '19 at 12:36
  • 1
    [Why must a short be converted to an int before arithmetic operations in C and C++?](https://stackoverflow.com/q/24371868/995714), [Is char default-promoted?](https://stackoverflow.com/q/11985774/995714), [Why does C/C++ automatically convert char/wchar_t/short/bool/enum types to int?](https://stackoverflow.com/q/20747614/995714), [Is promotion to int required by the C++ standard?](https://stackoverflow.com/q/23635240/995714) – phuclv Aug 22 '19 at 12:37
  • One of the reason might be related to the fact that if you do something like `auto x = 20 * 30;`, you probably expect 600 and not 88 (or -168) as 8 bit number would easily overflow. – Phil1970 Aug 22 '19 at 12:38
  • The cppreference article about [integral promotion](https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion). – Ron Aug 22 '19 at 12:39
  • @Phil1970 Both `20` and `30` are `int`, not "8 bit number" – Lightness Races in Orbit Aug 22 '19 at 12:39

1 Answers1

7

Pretty much every arithmetic operation performs what's called the usual arithmetic conversions.

This goes back decades.

First, integral promotions are performed.

  • No arithmetic operation takes uint8_t so both of your operands will always be promoted.

After that, a common type is found and conversions take place if necessary.

  • You can prevent this by casting the right-hand-side to the type of i but, per the above rule, that doesn't get you anything in this case.

(You can learn more about this process here and here.)

The upshot is that the result of your expression is never going to be uint8_t; it's just that in the case of j you've cast it back to uint8_t, with the wraparound that consequently ensues.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055