表达式的类型

rai*_*ner 3 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
}
Run Code Online (Sandbox Code Playgroud)

我试图弄清楚C++(尝试使用gcc 4.7.2)如何从表达式定义类型(更具体地说,它的签名).对于情况1,3和4,通常的算术转换应该将两个值都提升为unsigned int:

 10 = b00000000000000000000000000001010
 20 = b00000000000000000000000000010100
Run Code Online (Sandbox Code Playgroud)

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

 10 = b00000000000000000000000000001010
-20 = b11111111111111111111111111101100
      b11111111111111111111111111110110
Run Code Online (Sandbox Code Playgroud)

将其解释为无符号整数,并得到4294967286 - 非常好.

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

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

所以,我的问题是:

  1. 我的演绎是否正确?
  2. 标准在哪里定义了这个?我在C或C++标准中找不到任何引用.
  3. 其他业务呢?我怀疑+,*等会工作方式相同,但对于移位和逻辑操作?

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

Rei*_*ica 7

转换遵循整数转换等级原则.简而言之,当积分操作数为:

  • 完全相同,没有转换发生.

  • 在相同大小的情况下,unsigned优先.

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

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

它受intC++ 11标准的影响.它也密切相关intunsigned int.这些适用于哪些运营商的内容包含在各个运营商的子章节中[expr]§9.

  • @rainer是的,操作数类型几乎总是决定结果的类型.异常:不考虑`<<`,`>>`,`<< =`和`>> =`中的移位计数操作数的类型; `==`,`!=`,`<`,`>`,`<=`,`> =`,`&&`和`||`总是产生`bool`(C++)或`int`(C ),与操作数类型无关. (3认同)