当我在C++中混合使用有符号和无符号类型时会发生什么?

kqhtkvqz  于 2023-05-08  发布在  其他
关注(0)|答案(3)|浏览(193)

我对类型转换有一些疑问,你能解释一下在这样的表达式中会发生什么吗?

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

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

hmtdttj4

hmtdttj41#

简单地说,如果你混合了相同等级的类型(按照intlong intlong long int的顺序),无符号类型“获胜”,计算在该无符号类型内执行。结果是相同的无符号类型。
如果你混合了不同等级的类型,那么等级较高的类型“获胜”,如果它可以表示等级较低的类型的所有值。在该类型中执行计算。结果就是这种类型。
最后,如果排名较高的类型不能表示排名较低的类型的所有值,则使用排名较高的类型的无符号版本。结果就是这种类型。
在你的例子中,你混合了相同等级的类型(intunsigned int),这意味着整个表达式在unsigned int类型中计算。正如您正确指出的那样,表达式现在是10 - 4294967254(对于32位int)。无符号类型遵循以2^324294967296)为模的模算术规则。如果仔细计算结果(可以用算术表示为10 - 4294967254 + 4294967296),结果将是预期的52

ilmyapht

ilmyapht2#

1)由于标准的提升规则,signed类型a在减法之前被提升为unsigned类型。这种提升是根据以下规则(C++标准4.7/2)进行的:
如果目标类型是无符号的,则结果值是与源整数全等的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。
代数上a成为一个非常大的正数,肯定大于u
2)u - a是一个匿名临时,并且将是unsigned类型。(您可以通过编写auto t = u - a并在调试器中检查t的类型来验证这一点。)从数学上讲,这将是一个负数,但在隐式转换为无符号类型时,会调用类似于上面的回绕规则。
简而言之,两个转换操作具有相等且相反的效果,并且结果将是52。在实践中,编译器可能会优化所有这些转换。

ipakzgxi

ipakzgxi3#

这里是反汇编代码说:
它首先将-42设置为其补码并进行子运算。所以结果是10 + 420x0000000000400835 <+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

相关问题