为什么C++将无符号字符值打印为负数?
Why does C++ prints unsigned char value as negative?
我试图理解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 char
到int
的(隐式)转换,该转换恰好执行-
(减法)操作。 每当尝试将任何整数运算应用于某个小于int
的整数类型的值时,都会发生此整数提升。
引自C++14
,第5.7章
加法运算符从左到右
+
和-
分组。通常的算术转换是针对 算术或枚举类型的操作数。
对于通常的算术转换,(特定于这种情况)
....
- 否则,应在两个操作数上执行积分提升 (4.5)
最后,关于整体促销,第 § 4.5 章
除整数转换的
bool
、char16_t
、char32_t
或wchar_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
当然,这不会告诉您所涉及的规则,但这是一个快速的起点,可以查看表达式的类型或验证您对表达式类型的假设。
- 如何循环打印顶点结构
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 如何在c++中打印目录
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 在线编译器中的分段C++没有打印消息
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 如何将结构插入到集合中并打印集合的成员
- 在循环C++中指定字符串之后,不会打印该字符串
- 以螺旋方式打印矩阵的程序.(工作不好)
- 从控制台中删除最后打印的元素
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何仅使用对象名称打印特定于对象的成员
- 回溯C++不打印函数,因此文件
- 在一定长度后从数组中打印时缺少整数
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- 在gem5中打印文件中的所有cache_blocks
- 打印数字图案
- Log4cpp:以UTC/GMT时区打印日期
- 如何使用gdb制作一个可以漂亮地打印每个对象的C++函数