4

考虑 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,通常的算术转换应将这两个值提升为无符号整数:

 10 = b00000000000000000000000000001010
 20 = b00000000000000000000000000010100

然后,它会做一个 2 的补码得到 -20 并添加它:

 10 = b00000000000000000000000000001010
-20 = b11111111111111111111111111101100
      b11111111111111111111111111110110

将其解释为无符号整数,您会得到 4294967286 - 非常好。

显然,对于案例 2,您会得到相同的计算/结果;但是,通常的算术转换应该导致两个操作数都被解释为有符号整数,并且结果似乎也被解释为有符号整数。

由此,我推断,如果操作数在通常的算术转换之后被签名,则结果是有符号的。否则,结果是无符号的。

所以,我的问题是:

  1. 我的推论正确吗?
  2. 标准在哪里定义了这一点?我在 C 或 C++ 标准中找不到对此的任何引用。
  3. 其他操作呢?我怀疑+,*等会以相同的方式工作,但是移位和逻辑操作呢?

编辑:这似乎与C++11 类型的(有符号 + 无符号)有关?,但我的问题的关键部分似乎从那里接受的答案中丢失了:在通常的算术转换之后,表达式的结果是否总是两个操作数的类型?

4

2 回答 2

7

转换遵循整数转换等级原则。简而言之,整数操作数的处理方式如下。

首先,每个小于的操作数int都被转换为int(如果原始类型的所有值都适合),否则转换为unsigned int

之后,如果(可能转换的)操作数类型是:

  • 完全一样,没有转换发生。

  • 大小相同,无符号优先。

  • 大小不同,较小的转换为较大的。如果较大是无符号的,较小的也将转换为无符号。

这种转换将操作数转换为相同的类型,这也是结果的类型。

它被[expr]§9C++11 标准所涵盖。它还与[conv]和密切相关[conv.rank]。具体适用于哪些运营商在[expr].

于 2013-03-27T15:07:42.370 回答
2

好的,这很简单,我只是误读了标准...来自 C++ 11, §5 [expr] p9:

许多期望算术或枚举类型的操作数的二元运算符会以类似的方式导致转换和产生结果类型。目的是产生一个通用类型,这也是结果的类型。这种模式称为通常的算术转换,...

于 2013-03-27T15:07:12.807 回答