我正在运行这段代码,我得到的输出值为(转换为十六进制)0xFFFFFF93和0xFFFFFF94。
#include <iostream>
using namespace std;
int main()
{
char x = 0x91;
char y = 0x02;
unsigned out;
out = x + y;
cout << out << endl;
out = x + y + 1;
cout << out << endl;
}
我对这里的算法感到困惑。是因为out中的所有高位都默认为1吗? 当我将类型转换为int时,我得到的答案为(在int中)-109和-108。知道为什么会这样吗?
答案 0 :(得分:4)
所以这里有很多事情要发生。一, char 可以是签名或未签名,在您的情况下,它是签名。两项任务将右侧转换为左侧的类型。使用正确的警告标志会有所帮助,clang
标有-Wconversion
标志警告:
warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
out = x + y;
~ ~~^~~
在这种情况下,要进行此转换,它基本上会将unsigned max + 1
添加或减去要转换的数字。
我们可以使用limits header:
看到相同的结果#include <limits>
//....
std::cout << std::hex << (std::numeric_limits<unsigned>::max() + 1) + (x+y) << std::endl ;
//...
结果是:
ffffff93
作为参考,draft C++ standard部分5.17
分配和复合赋值运算符表示:
如果左操作数不是类类型,则表达式被隐式转换(第4节)到左操作数的cv-unqualified类型。
4.7
积分转换下的第4条说:
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 后注]
相当于添加或减去UMAX + 1
。
答案 1 :(得分:2)
普通char
通常也代表签名类型!由于C语法的兼容性原因,这未进一步指定,并且可能依赖于编译器实现。通过明确指定signed
/ unsigned
关键字,您始终可以使其具有独特的签名算术行为。
尝试替换像这样的字符定义
unsigned char x = 0x91;
unsigned char y = 0x02;
获得您期望的结果!
查看完整的示例here。
答案 2 :(得分:0)
负数在内部表示为2的补码,因此,它们的第一位是1.当您使用十六进制(并以十六进制打印)时,有效位显示为1,导致您显示的数字。
答案 3 :(得分:0)
C ++没有指定char是否为signed or unsigned。这里它们是有符号的,所以当它们被提升为int时,使用负值,然后将其转换为unsigned。使用或转换为unsigned char
。