1

What is type if uint8_t value multiplied by uint8_t? For example:

#include <iostream>

int main()
{
    uint8_t a = 'a', b = 'b';
    std::cout << a * b;
}

The output of the program is 9506. Will a * b be uint32_t type data?
Why not still be a uint8_t type?
Thanks.

leiyc
  • 903
  • 11
  • 23
  • The smallest integer type that a C++ program evaluates expressions with is `int`. Any smaller type `sizeof(uint_8) < sizeof(int)` will cause the values to be promoted before the operation. The result of an operation is always the same types as the input value (in this case after promotion). See: https://stackoverflow.com/a/5563131/14065 Ther last case applies `Both operands are promoted to int` – Martin York Aug 30 '19 at 11:34
  • Incidentally, the result of multiplying two 8-bit values will fit in 16 bits. – Pete Becker Aug 30 '19 at 13:34

2 Answers2

5

Due to integer promotion rules in C++ integer types narrower than int in usual arithmetic operations are promoted to int before the operation is applied (simplified explanation).

You can observe this at https://cppinsights.io/ (neat tool right?):

#include <cstdint>

int main()
{
    uint8_t a = 'a', b = 'b';
    [[mayebe_unsued]] auto r = a * b; // <-- pay attention here
}

is converted internally by the compiler to:

#include <cstdint>

int main()
{
  uint8_t a = static_cast<unsigned char>('a');
  uint8_t b = static_cast<unsigned char>('b');
  int r = static_cast<int>(a) * static_cast<int>(b); // <-- pay attention here
}

As to why, well, it was considered wayback that operations with operands in the platform native type (int) are faster than with operands with narrower types. I honestly don't know how much truth is to this in modern architectures.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • Note: Remember the `as if` rule. If the value was assigned back to `unint8_t` and multiplication of `uint8_t` was faster than int the compiler could use this as the observable result would be the same. – Martin York Aug 30 '19 at 11:38
3

What's happening is that uint8_t is being promoted to int, because everything smaller than int is converted into an int before they can be multiplied / added / etc.

You cannot stop this, but you can cast it back (By assigning it to a uint8_t variable or casting it as static_cast<uint8_t>(a * b))

Artyer
  • 31,034
  • 3
  • 47
  • 75