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

坚强是说给别人听的谎言 提交于 2021-01-27 11:45:12

问题


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?


回答1:


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.




回答2:


You're missing the (implicit) conversion from unsigned char to int that happens to perform the - (subtract) operation. This integer promotion happens any time you try to apply any integer operation to a value of some integral type smaller than int.




回答3:


There are answers here showing what is happening. I won't repeat. I am going to give you a simple tool to help you.

Here is a trick you can do to quickly find the type of an expression:

template <class> struct Name; // purposely no definition given

Name<decltype(your_expression)> n;

This will generate a compiler error for undefined template 'Name', but what we are really interested in is the type of the template argument which will appear in the error message.

E.g. if you want to see what type you get when you do arithmetic between two unsigned char:

#include <utility>
template <class> struct Name;

auto test()
{
    Name<decltype(std::declval<unsigned char>() - std::declval<unsigned char>())> n;

   // or
   unsigned char a{};
   Name<decltype(a - a)> n2;
}

will get you

error: implicit instantiation of undefined template 'Name<int>'

which will show you that the type of the expression is int

Of course this won't tell you the rules involved, but it is a quick starting point to see the type of the expression or to verify your assumption of the type of the expression.



来源:https://stackoverflow.com/questions/48372792/why-does-c-prints-unsigned-char-value-as-negative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!