问题
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
, orwchar_t
whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of typeint
if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of typeunsigned 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