Search code examples
c++charunsignedtype-promotion

Why does C++ prints unsigned char value as negative?


I'm trying to understand the implicit conversion rules in C++ and I understood that when there are one operation between two primary types the "lower type" is promoted to the "higher type", so let say for:

int a = 5;
float b = 0.5;

std::cout << a + b << "\n";

should print 5.5 because 'a' gets promoted to float type. I also understood that unsigned types are "higher types" than the signed counter parts so:

int c = 5;
unsigned int d = 10;

std::cout << c - d << "\n";

prints 4294967291 because 'c' gets promoted to a unsigned int and since unsigned types wraps around when less than zero we get that big number.

However for the following case I don't understand why I am getting -105 instead of a positive number.

#include <iostream>

int main(void) {
    unsigned char a = 150;
    std::cout << static_cast<int>(a - static_cast<unsigned char>(255)) << "\n";
    return 0;
}

I guess that this code:

a - static_cast<unsigned char>(255)

should result in a positive number so the final cast (to int) shouldn't affect the final result right?


Solution

  • Quoting from C++14, chapter § 5.7

    The additive operators + and - group left-to-right. The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.

    and for usual arithmetic conversions, (specific for this case)

    ....

    • Otherwise, the integral promotions (4.5) shall be performed on both operands

    and, finally, for integral promotions, chapter § 4.5

    A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

    Hence, the unsigned char operands are promoted to int and then , the result is calculated.