有符号整数溢出是什么?

时间:2017-10-17 12:04:18

标签: c cs50

我从CS50学习C语言。当我运行我的代码时,它表示“已签名的整数溢出”#。

#include <stdio.h>
#include <cs50.h>

int main(void)
{
    int x = 41;
    int c = 0;
    while(x>=25)
    {
      c = c+1;
    }

    printf("%i\n", c);
}

有人可以解释这意味着什么吗?

5 个答案:

答案 0 :(得分:1)

您的while条件将始终为true,这意味着循环将永远运行,在每次迭代中向c添加1。

由于c是(signedint,这意味着它会缓慢增加到它的最大值,之后下一个增量将是UB(未定义的行为) )。许多机器在这个特定的UB中会做的是将c变为负数,我猜这不是你想要的。这是由于称为&#34;有符号整数溢出&#34;。

的现象

我们假设32位int并使用两个补码signed int在二进制sign bit (0 for positive, 1 for negative) | 31 bits中看起来像这样。零看起来像000...00,类似于000...01,依此类推。

Max signed int看起来像0111...112,147,483,647)。向此数字添加1时,您将获得100...000,这会翻转符号位,现在会产生负数。向此添加另一个将导致100...001再次具有符号位意味着它仍然是负数...

c声明为未签名会确保c仍然是非负面的。此外,使用while(x-- >= 25)结束循环也可能是一个好主意:)

答案 1 :(得分:0)

嗯......你有一个无限循环,因为你的值x总是大于25,因为你不减少它。
因为循环是无限的,你的值c到达int的最大大小(如果是4bytes则为2,147,483,647)。 你可以试试这个以逃避无限循环:

int main(void)
{
    int x = 41;
    int c = 0;

    while (x >= 25)
    {
      c = c+1;
      x--;
    }
    printf("%i\n", c);
}

答案 2 :(得分:0)

首先,您需要知道“有符号整数溢出条件”是什么。

当数学运算导致数字超出数据类型的范围时,会出现这种情况,在您的情况下,这是有符号整数溢出。

这是因为你的循环无限循环,因为x >= 25将永远为真。

答案 3 :(得分:0)

&#34;有符号整数溢出&#34;表示您尝试存储的值超出了该类型可以表示的值范围,并且该操作的结果是 undefined (在这种特殊情况下,您的程序会暂停误差)。

由于您的while循环永不终止(x >= 25评估为true,而您永远不会更改x的值),因此您需要向c添加1才能到达超出签名int可以表示范围的值。

请记住,在C中,积分和浮点类型具有固定大小,这意味着它们只能表示固定数量的值。例如,假设int是3位宽,这意味着它只能存储8个不同的值。这些值取决于位模式的解释方式。你可以存储&#34; unsigned&#34; (非负)值[0..7],或&#34;签署&#34; (负数和非负数)值[-3...3][-4..3]取决于表示形式。您可以通过以下几种方法来解释三位的值:

Bits    Unsigned    Sign-Magnitude    1's Complement    2's Complement
----    --------    -------------     --------------    -------------- 
 000           0                0                  0                 0
 001           1                1                  1                 1
 010           2                2                  2                 2
 011           3                3                  3                 3
 100           4               -0                 -3                -4
 101           5               -1                 -2                -3
 110           6               -2                 -1                -2
 111           7               -3                 -0                -1

大多数系统使用2的补码作为有符号整数值。是的,符号幅度和1的补码具有零的正负表示。

所以,让我们说c是我们的3位签名int。我们从0开始,每次循环添加1。在c3之前,Eveything没问题 - 使用我们的3位有符号表示法,我们无法表示值4。操作的结果是未定义的行为,这意味着编译器不需要以任何特定方式处理该问题。从逻辑上讲,你期望价值能够回归&#34;根据使用中的表示形式为负值,但即使这样也不一定正确,这取决于编译器如何优化算术运算。

请注意,无符号整数溢出是明确定义的 - 您可以绕过&#34;#34;回到0.

答案 4 :(得分:0)

一个整数在达到最大值之前只能容纳这么多数字。在你的 while 循环中,它说在 x>=25 时执行它。由于 x 是 41 并且 x 的值永远不会减少,这意味着 while 循环将始终执行,因为它从 41>=25 起始终为真。

一个整数最多只能容纳数字 2,147,483,647,这意味着由于 C 将继续添加到自身,因为一旦达到 2,147,483,647,while 循环将始终为真它会给你一个错误,因为一个整数不能超过那个它没有足够的内存。