为什么C++将无符号字符值打印为负数?

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

本文关键字:打印 C++ 无符号 字符 为什么      更新时间:2023-10-16

我试图理解C++中的隐式转换规则,我理解当两个主要类型之间有一个操作时,"较低类型"将提升为"高级类型",因此请说:

int a = 5;
float b = 0.5;
std::cout << a + b << "n";

应该打印 5.5,因为"a"被提升为浮点型。我还了解到无符号类型比有符号对应部分"更高类型",因此:

int c = 5;
unsigned int d = 10;
std::cout << c - d << "n";

打印4294967291因为"c"被提升为无符号 int,并且由于无符号类型在小于零时环绕,我们得到那么大的数字。

但是对于以下情况,我不明白为什么我得到 -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 charint的(隐式)转换,该转换恰好执行-(减法)操作。 每当尝试将任何整数运算应用于某个小于int的整数类型的值时,都会发生此整数提升。

引自C++14,第5.7章

加法运算符从左到右+-分组。通常的算术转换是针对 算术或枚举类型的操作数。

对于通常的算术转换,(特定于这种情况)

....

  • 否则,应在两个操作数上执行积分提升 (4.5)

最后,关于整体促销,第 § 4.5 章

除整数

转换的boolchar16_tchar32_twchar_t以外的整数类型的 prvalue 秩 (4.13) 小于 int 的秩 如果 int 可以int表示所有 源类型的值;否则,可以将源 prvalue 转换为类型为unsigned int.的 prvalue

因此,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

当然,这不会告诉您所涉及的规则,但这是一个快速的起点,可以查看表达式的类型或验证您对表达式类型的假设。