为什么 C++ 将 unsigned char 值打印为负数?
Why does C++ prints unsigned char value as negative?
我正在尝试了解 C++ 中的隐式转换规则,并且我了解到当两种主要类型之间存在一个操作时,"lower type" 被提升为 "higher type",所以假设:
int a = 5;
float b = 0.5;
std::cout << a + b << "\n";
应该打印 5.5 因为 'a' 被提升为 float 类型。我也明白无符号类型比有符号的计数器部分 "higher types" 所以:
int c = 5;
unsigned int d = 10;
std::cout << c - d << "\n";
打印 4294967291 因为 'c' 被提升为无符号整数,并且由于无符号类型在小于零时回绕,我们得到那个大数字。
但是对于以下情况,我不明白为什么我得到的是 -105 而不是正数。
#include <iostream>
int main(void) {
unsigned char a = 150;
std::cout << static_cast<int>(a - static_cast<unsigned char>(255)) << "\n";
return 0;
}
我猜这个代码:
a - static_cast<unsigned char>(255)
结果应该是正数,所以最后的转换(到 int)不应该影响最终结果对吗?
您缺少从 unsigned char
到 int
的(隐式)转换,而恰好执行 -
(减)操作。每当您尝试将任何整数运算应用于小于 int
.
的某个整数类型的值时,都会发生此整数提升
引自 C++14
,章节 § 5.7
The additive operators +
and -
group left-to-right. The usual arithmetic conversions are performed for
operands of arithmetic or enumeration type.
和通常的算术转换,(特定于这种情况)
....
- Otherwise, the integral promotions (4.5) shall be performed on both operands
最后,积分促销,第 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.
因此,unsigned char
操作数被提升为int
,然后计算结果。
这里有答案显示正在发生的事情。我不会重复。我将给你一个简单的工具来帮助你。
这里有一个技巧可以快速找到表达式的类型:
template <class> struct Name; // purposely no definition given
Name<decltype(your_expression)> n;
这将为未定义的模板生成编译器错误 'Name',但我们真正感兴趣的是将出现在错误消息中的模板参数的类型。
例如如果你想看看在两个 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;
}
会得到你
error: implicit instantiation of undefined template 'Name<int>'
这会告诉你表达式的类型是 int
当然这不会告诉您所涉及的规则,但这是查看表达式类型或验证您对表达式类型的假设的快速起点。
我正在尝试了解 C++ 中的隐式转换规则,并且我了解到当两种主要类型之间存在一个操作时,"lower type" 被提升为 "higher type",所以假设:
int a = 5;
float b = 0.5;
std::cout << a + b << "\n";
应该打印 5.5 因为 'a' 被提升为 float 类型。我也明白无符号类型比有符号的计数器部分 "higher types" 所以:
int c = 5;
unsigned int d = 10;
std::cout << c - d << "\n";
打印 4294967291 因为 'c' 被提升为无符号整数,并且由于无符号类型在小于零时回绕,我们得到那个大数字。
但是对于以下情况,我不明白为什么我得到的是 -105 而不是正数。
#include <iostream>
int main(void) {
unsigned char a = 150;
std::cout << static_cast<int>(a - static_cast<unsigned char>(255)) << "\n";
return 0;
}
我猜这个代码:
a - static_cast<unsigned char>(255)
结果应该是正数,所以最后的转换(到 int)不应该影响最终结果对吗?
您缺少从 unsigned char
到 int
的(隐式)转换,而恰好执行 -
(减)操作。每当您尝试将任何整数运算应用于小于 int
.
引自 C++14
,章节 § 5.7
The additive operators
+
and-
group left-to-right. The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.
和通常的算术转换,(特定于这种情况)
....
- Otherwise, the integral promotions (4.5) shall be performed on both operands
最后,积分促销,第 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.
因此,unsigned char
操作数被提升为int
,然后计算结果。
这里有答案显示正在发生的事情。我不会重复。我将给你一个简单的工具来帮助你。
这里有一个技巧可以快速找到表达式的类型:
template <class> struct Name; // purposely no definition given
Name<decltype(your_expression)> n;
这将为未定义的模板生成编译器错误 'Name',但我们真正感兴趣的是将出现在错误消息中的模板参数的类型。
例如如果你想看看在两个 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;
}
会得到你
error: implicit instantiation of undefined template 'Name<int>'
这会告诉你表达式的类型是 int
当然这不会告诉您所涉及的规则,但这是查看表达式类型或验证您对表达式类型的假设的快速起点。