考虑以下代码片段:
#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;
}
Run Code Online (Sandbox Code Playgroud)
这给出了以下输出:
#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;
}
Run Code Online (Sandbox Code Playgroud)
为什么是b和d两者0?我似乎找不到对此的解释。
这种行为称为溢出。uint32_t占用 4 字节或 32 位内存。当您使用时,UINT32_MAX您将 32 位中的每一个都设置为 1,这是 4 字节内存可以表示的最大值。1是一个整数文字,通常也占用 4 个字节的内存。因此,您基本上是在 4 个字节可以表示的最大值上加 1。这是最大值在内存中的样子:
1111 1111 1111 1111 1111 1111 1111 1111
Run Code Online (Sandbox Code Playgroud)
当您为此添加 1 时,没有更多空间来表示大于最大值的 1,因此所有位都设置为 0 并返回到它们的最小值。尽管您要分配给uint64_t容量为 两倍的uint32_t,但它仅在加法操作完成后才分配。加法运算检查左右操作数的类型,这决定了结果的类型。如果至少一个值是 type uint64_t,则另一个操作数也会自动提升uint64_t。如果你这样做:
(UINT32_MAX) + (uint64_t)1;
Run Code Online (Sandbox Code Playgroud)
或者:
(unint64_t)(UINT32_MAX) + 1;
Run Code Online (Sandbox Code Playgroud)
,你会得到你所期望的。在像 C# 这样的语言中,您可以使用checked块来检查溢出并防止这种情况发生。
| 归档时间: |
|
| 查看次数: |
378 次 |
| 最近记录: |