考虑C ++程序的以下部分;打印到控制台的值作为注释给出。
{ // case 1
unsigned int x = 10;
unsigned int y = 20;
std::cout << "u/u x - y: " << x-y << std::endl; // 4294967286
}
{ // case 2
int x = 10;
int y = 20;
std::cout << "s/s x - y: " << x-y << std::endl; // -10
}
{ // case 3
unsigned int x = 10;
int y = 20;
std::cout << "u/s x - y: " << x-y << std::endl; // 4294967286
}
{ // case 4
int x = 10;
unsigned int y = 20;
std::cout << "s/u x - y: " << x-y << std::endl; // 4294967286
}
我试图弄清楚C ++(尝试使用gcc 4.7.2)如何从表达式定义类型(更具体地说,它的签名)。对于情况1,3和4,通常的算术转换应该将两个值都提升为unsigned int:
10 = b00000000000000000000000000001010
20 = b00000000000000000000000000010100
然后,它会做2的补充以获得-20并添加它:
10 = b00000000000000000000000000001010
-20 = b11111111111111111111111111101100
b11111111111111111111111111110110
将其解释为无符号整数,并获得4294967286 - 非常好。
显然,你得到案例2的相同计算/结果;但是,通常的算术转换应该导致两个操作数被解释为有符号的int,并且结果似乎被解释为 signed 整数。
由此,我推断,如果在通常的算术转换之后对操作数进行了签名,则结果将被签名。否则,结果是无符号的。
所以,我的问题是:
+
,*
等会以同样的方式运作,但是转换和逻辑运算呢?编辑:这似乎与C++11 type of (signed + unsigned)?有关,但是我的问题的关键部分似乎从那里接受的答案中遗漏了:表达式的结果总是会是通常的算术转换后的两个操作数?
答案 0 :(得分:7)
转化遵循整数转换等级原则。简而言之,整数操作数的处理如下。
首先,小于int
的每个操作数都会转换为int
(如果原始类型的所有值都适合),或者如果不符合,则转换为unsigned int
。
之后,如果(可能转换的)操作数类型是:
完全一样,没有转换。
具有相同的大小,无符号优先。
,较小的转换为较大。如果较大的是无符号,则较小的也将转换为无符号。
此转换将操作数转换为相同的类型,这也是结果的类型。
它由C ++ 11标准的[expr]§9
涵盖。它还与[conv]
和[conv.rank]
密切相关。 {@ 1}}的子章节中的各个运营商描述中涵盖了适用于哪些运营商。
答案 1 :(得分:2)
好的,这很简单,我只是误读标准......来自C ++ 11,§5[expr] p9:
许多期望算术或算术操作数的二元运算符 枚举类型导致转换并产生类似的结果类型 办法。 目的是产生一种通用类型,它也是一种类型 结果。这种模式称为通常的算术转换,...