为什么我会得到这些有符号/无符号整数溢出的结果?

问题描述 投票:0回答:4

我刚刚开始自学 C++,并开始学习整数溢出。出于好奇,我编写了一些测试,只是为了看看某些整数值会发生什么。

这是我的程序:

#include <iostream>

int main()
{
    int x(0);
    std::cout << x << std::endl;

    x = x + 2147483647;
    std::cout << x << std::endl;

    x = x + 1;
    std::cout << x << std::endl;
    std::cout << std::endl;

    unsigned int y(0);
    std::cout << y << std::endl;

    y = y + 4294967295;
    std::cout << y << std::endl;

    y = y + 1;
    std::cout << y << std::endl;
}

这是输出:

0
2147483647
-2147483648

0
4294967295
0

输出让我有点惊讶,我想知道是否有人可以解释为什么会发生这种情况,或者这些结果的意外性是否是预期的;所以这可能只是我的特定机器的结果。

c++ integer-overflow
4个回答
9
投票

有符号整数溢出是未定义的行为,而无符号整数溢出是明确定义的;值环绕。换句话说,该值除以 2bits,其中 bits 是数据类型中的位数。因为你有 32 位

int

4294967295 + 1 = 4294967296 % 232 = 0

在第二种情况下结果为 0。从语言的角度来看,第一种情况是未定义的。

但是,大多数实现都采用 2 的补码 来实现 有符号整数类型。使用 2 的补码实现的带符号 4 位数据类型的玩具可用于解释第一种情况中发生的情况。在这种类型

POS_MAX = 7 = 0111)2

NEG_MAX = -8 = 1000)2

该类型可以容纳 24 = 16 个状态,8 个正(0 到 7)和 8 个负(-1 到 -8)。

POS_MAX + 1 = 0111)2 + 1)2 = 1000)2

由于第一位已设置,因此它是一个负数,要找到实际值,请执行二进制补码的逆运算(减去 1 并翻转位)

1000)2 - 1)2 = 0111)2

~0111)2=1000)2=8

因此最终值为

-8
。所有这些都不是由语言定义的,但这就是您的案例中具体发生的情况。


7
投票

整数(通常)采用 32 位表示。如果有 32 位,则可以寻址从 0 到 231-1。即,

00000000000000000000000000000000
00000000000000000000000000000001
.
.
.
01111111111111111111111111111111
^-------------------------------
signed bit

0 表示正数,1 表示负数。

如果将 1 加到

01111111111111111111111111111111
,则会得到
10000000000000000000000000000000
,十进制为 -2147483648。

使用无符号整数,没有符号位,并且事实上,可以有一个最大有符号整数两倍的数字。但是,当数字再次滚动时(即

11111111111111111111111111111111
+
00000000000000000000000000000001
),您只需回滚到
00000000000000000000000000000000
即可。

为了更深入地理解,您可以查看补码,这是整数在计算机中的表示方式。


1
投票

整数有两种类型。有符号和无符号,传统上都是 32 位。

在第一种情况下,您使用的是有符号整数。在这种情况下,1 位保留用于符号,其余 31 位用于保留大小。在这种情况下,可以保存的最大数字是 2^31 - 1 = 2147483647。加一会影响最高有效位,将数字变为负数。 (Google 2 的数字补码表示法以了解更多详细信息)。

在第二种情况下,您使用的是 unsigned int,其中所有 32 位都保留用于大小。因此,存储的最大数字是 2^32 - 1。加一将为零。例如,假设我们有 3 位数字系统,111 = 7。加 1 将使其变为 1000,但由于它是 3 位系统,它将变为 000 = 0


-1
投票

阅读补码。基本上,一旦达到处理器可以支持的最大整数并向其加 1,通过打开“符号”位,它就会变成负数。

© www.soinside.com 2019 - 2024. All rights reserved.