表达式的类型

时间:2013-03-27 14:56:39

标签: c++ c language-lawyer

考虑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 整数。

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

所以,我的问题是:

  1. 我的演绎是否正确?
  2. 标准在哪里定义?我在C或C ++标准中找不到任何引用。
  3. 其他操作怎么样?我怀疑+*等会以同样的方式运作,但是转换和逻辑运算呢?
  4. 编辑:这似乎与C++11 type of (signed + unsigned)?有关,但是我的问题的关键部分似乎从那里接受的答案中遗漏了:表达式的结果总是会是通常的算术转换后的两个操作数?

2 个答案:

答案 0 :(得分:7)

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

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

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

  • 完全一样,没有转换。

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

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

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

它由C ++ 11标准的[expr]§9涵盖。它还与[conv][conv.rank]密切相关。 {@ 1}}的子章节中的各个运营商描述中涵盖了适用于哪些运营商。

答案 1 :(得分:2)

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

  

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