我正在学习C ++语言,我对类型转换有一些疑问,你能解释一下这样的表达式会发生什么:
unsigned int u = 10;
int a = -42;
std::cout << u - a << std::endl;
这里我知道如果我在有两个数学运算符时应用规则,结果将是52.但是我想知道当编译器将a转换为无符号值时会发生什么情况会产生一个临时的无符号类型,之后会发生什么?现在的表达式应为10 -4294967254。
答案 0 :(得分:17)
简单来说,如果您混合相同排名的类型(按int
,long int
,long long int
的顺序),则无符号类型&#34;胜出&#34;并且计算在该无符号类型内执行。结果是相同的无符号类型。
如果你混合不同级别的类型,排名较高的类型&#34;胜出&#34;,如果它可以代表较低排名类型的所有值。计算在该类型内执行。结果是那种类型。
最后,如果排名较高的类型不能代表较低排名类型的所有值,则使用较高排名类型的无符号版本。结果是那种类型。
在您的情况下,您混合了相同等级(int
和unsigned int
)的类型,这意味着整个表达式在unsigned int
类型中进行评估。正如您所说,表达式现在是10 - 4294967254
(对于32位int
)。无符号类型遵循以2^32
(4294967296
)为模的模运算规则。如果仔细计算结果(可以算术表示为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