当我混合有符号和无符号类型时会发生什么?

时间:2014-09-01 15:32:31

标签: c++ expression unsigned built-in-types

我正在学习C ++语言,我对类型转换有一些疑问,你能解释一下这样的表达式会发生什么:

unsigned int u = 10; 
int a = -42; 
std::cout << u - a << std::endl;

这里我知道如果我在有两个数学运算符时应用规则,结果将是52.但是我想知道当编译器将a转换为无符号值时会发生什么情况会产生一个临时的无符号类型,之后会发生什么?现在的表达式应为10 -4294967254。

3 个答案:

答案 0 :(得分:17)

简单来说,如果您混合相同排名的类型(按intlong intlong long int的顺序),则无符号类型&#34;胜出&#34;并且计算在该无符号类型内执行。结果是相同的无符号类型。

如果你混合不同级别的类型,排名较高的类型&#34;胜出&#34;,如果它可以代表较低排名类型的所有值。计算在该类型内执行。结果是那种类型。

最后,如果排名较高的类型不能代表较低排名类型的所有值,则使用较高排名类型的无符号版本。结果是那种类型。

在您的情况下,您混合了相同等级(intunsigned int)的类型,这意味着整个表达式在unsigned int类型中进行评估。正如您所说,表达式现在是10 - 4294967254(对于32位int)。无符号类型遵循以2^324294967296)为模的模运算规则。如果仔细计算结果(可以算术表示为10 - 4294967254 + 4294967296),则结果为预期52

答案 1 :(得分:3)

1)由于标准促销规则,signed类型a在减法之前会提升为unsigned类型。根据此规则(C ++标准4.7 / 2)进行促销:

  

如果目标类型是无符号的,则结果值最小   无符号整数与源整数一致(模2n,其中n是   用于表示无符号类型的位数。)

代数a变成一个非常大的正数,肯定大于u

2)u - a是一个匿名临时用户,将是无符号类型。 (您可以通过编写auto t = u - a并检查调试器中t的类型来验证这一点。)数学上这将是一个负数,但在隐式转换为无符号类型时,类似于上面的环绕规则是调用

简而言之,两个转换操作具有相同和相反的效果,结果将是52.实际上,编译器可能会优化所有这些转换。

答案 2 :(得分:-1)

这里是反汇编代码:

首先将-42设置为其补码并执行子操作。所以结果是10 + 42     0x0000000000400835 <+8>: movl $0xa,-0xc(%rbp) 0x000000000040083c <+15>: movl $0xffffffd6,-0x8(%rbp) 0x0000000000400843 <+22>: mov -0x8(%rbp),%eax 0x0000000000400846 <+25>: mov -0xc(%rbp),%edx 0x0000000000400849 <+28>: sub %eax,%edx 0x000000000040084b <+30>: mov %edx,%eax