Signed int 未能转换为 unsigned int。

4
我正在阅读Lippman和Lajoie的书《C++ Primer》。在第65页上,他们说: 如果我们在算术表达式中同时使用unsigned和int值,则int值通常会转换为unsigned。 如果我尝试他们的示例,事情会按预期工作,也就是说:
unsigned u = 10;
int i = -42;
std::cout << u + i << std::endl; // if 32-bit ints, prints 4294967264

然而,如果我把 i 改为 -10,在32位整数的情况下,得到的结果是0,而不是预期的4294967296:

unsigned u = 10;
int i = -10;
std::cout << u + i << std::endl; // prins 0 instead of 4294967296. Why?

这个表达式应该打印出10 + (-10 mod 2^32)才对吧?

8
"4294967296等于2的32次方",而"2的32次方模2的32次方"等于"0"。 - HolyBlackCat
1
你还需要将 +(对于无符号整数)的结果模 2^width。 - user17732522
哦...所以我需要再次取模2^width吗?这部分我不是很理解。如果我已经将有符号数转换为无符号数,并且整个表达式产生的结果是无符号数,为什么我还需要再次“包装”结果呢? - Jose Lopez Garcia
1
好的...现在我明白了。结果不适合无符号,所以最终结果再次“包装”。在它被投票降低之前,我应该删除这个问题吗?感谢您的帮助。 - Jose Lopez Garcia
1
“-10”首先被提升为“unsigned”,得到“4294967286”。 “4294967286 + 10”是“4294967296”,这是“2 ** 32”,超出了“unsigned”的范围,因此发生了无符号整数溢出,最终结果为“0”。 - Yksisarvinen
将-10转换为32位无符号数后,其值为4294967286(应用模算术后)。因此,计算u + i的结果为10 + 4294967286,即在数学上为4294967296。但是,该值超过了32位无符号数可以表示的最大值,因此模算术再次产生作用,得到一个结果为0u。 - Peter
1个回答

3

无符号整数unsigned int和有符号整数int在内存中占用32位,让我们考虑它们的位表示:

unsigned int u = 10;
00000000000000000000000000001010

int i = -42;
11111111111111111111111111010110

u + i:
11111111111111111111111111100000

如果我们将11111111111111111111111111100000作为有符号数(int)处理,则它是-32:enter image description here 如果我们将其作为无符号数(unsigned)处理,则它是4294967264:enter image description here 区别在于最高位,它是表示-2^31还是+2^31。
现在让我们来看一下(10u) + (-10)
   unsigned int u = 10;
   00000000000000000000000000001010

   int i = -10;
   11111111111111111111111111110110

   u + i:
(1)00000000000000000000000000000000

由于 u + i 结果将超过32位的限制,因此最高位的 1 将被舍弃。由于剩下的32位都是零,结果将为0。同样地,如果 i = -9,那么结果将为1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接