考虑以下代码片段:
#include <cstdint>
#include <limits>
#include <iostream>
int main(void)
{
uint64_t a = UINT32_MAX;
std::cout << "a: " << a << std::endl;
++a;
std::cout << "a: " << a << std::endl;
uint64_t b = (UINT32_MAX) + 1;
std::cout << "b: " << b << std::endl;
uint64_t c = std::numeric_limits<uint32_t>::max();
std::cout << "c: " << c << std::endl;
uint64_t d = std::numeric_limits<uint32_t>::max() + 1;
std::cout << "d: " << d << std::endl;
return 0;
}
它提供了以下输出:
a: 4294967295
a: 4294967296
b: 0
c: 4294967295
d: 0
为什么b
和d
都是0
?我似乎找不到这方面的解释。
发布于 2020-07-10 07:06:21
这种行为称为溢出。uint32_t
占用4个字节或32位内存。当您使用UINT32_MAX
时,您将32位中的每一位设置为1,这是4字节内存可以表示的最大值。1
是一个整数文本,通常也占用4个字节的内存。因此,基本上是将1添加到最大值,4个字节可以表示。内存中的最大值是这样的:
1111 1111 1111 1111 1111 1111 1111 1111
在此添加一个时,没有更多的空间来表示大于最大值的值,因此所有位都被设置为0并返回到它们的最小值。虽然分配给的uint64_t
的容量是uint32_t
的两倍,但只有在加法操作完成后才分配。加法操作检查左操作数和右操作数的类型,这就是结果的类型。如果至少有一个值是uint64_t
类型的,则另一个操作数也会自动提升到uint64_t
。如果你这样做了:
(UINT32_MAX) + (uint64_t)1;
或者:
(unint64_t)(UINT32_MAX) + 1;
你会得到你所期望的。在像C#这样的语言中,您可以使用checked
块检查溢出,并隐式地防止这种情况发生。
https://stackoverflow.com/questions/62828526
复制相似问题