整数溢出(将使程序中的整数变为负数的最小文件大小)

时间:2019-07-02 17:56:20

标签: c

我用C语言编写了一个数字符号计算器。我需要知道文件的最小大小(以字节为单位),这会导致签名为负数

程序以char形式从文件中读取字节,然后将其存储为整数,并不断增加对整数的使用,直到达到EOF。该程序工作正常。

FILE *fp;
char inpfile[20];
char c;
int sumdigsig = 0;

// reading in the name of the file using inpfile
printf("Please Enter name of the File:\n");
scanf("%s",inpfile);
// checking if the file exisits
if((fp = fopen(inpfile,"r")) == NULL){
        fprintf(stderr,"File does no Exsist\n");
        exit(1);
}
// If the file exsists using fgetc to read in until endoffile is reached
// and casting char to int and suming it 
  c = fgetc(fp);
while(c != EOF){
        sumdigsig += (int)c;
        c = fgetc(fp);
}
printf("%d\n",sumdigsig);

}

该程序运行正常,它只是一个参考,因此您可以了解正在发生的事情。运行很大的文件会导致预期的负数,但是我需要知道什么文件大小(以位为单位)将导致整数溢出并为负数。

2 个答案:

答案 0 :(得分:2)

我需要知道什么文件大小(以位为单位)会导致整数溢出并为负数。

(您是说“文件大小为字节”吗?文件很少以位为单位。)

您的操作方式取决于文件中的字节。一旦您相加的字节总和超过INT_MAX(请参阅limits.h),int累积总和的值将换为负值。

因此,特定文件的最大字节数 将比导致总和超过INT_MAX的字节数少一。也就是说,比您在总和首次超过INT_MAX时从文件中读取的字节数少一个字节;或者,从在代码中检测到这一点的实际意义上讲,它首先变为负数。

而且,正如评论之一指出的那样,如果所有字节都是0x00,那么即使是无限大的文件也永远不会满足此条件。

编辑1:关于未定义溢出行为的注释,不是检测总和是否为负,而是测试(INT_MAX - sum)是否小于最新值。读取字节的值,之前,将该字节的值添加到总和中。

编辑2:用代码表示:

我将其重写的核心循环

c = 0;
bytes = 0;
while (1) {
    if ((c = fgetc(fp)) == EOF) break;

    if ((INT_MAX - sumdigsig) >= c) {
        sumdigsig += c;
        bytes++;
    } else {
        break;
    }
}

示例运行

head -c 1073741824 < /dev/urandom > large-file-of-random-bytes

./sum-file-bytes
Please Enter name of the File : large-file-of-random-bytes
sum is : 2147483572; read 16845621 bytes to reach that sum

head -c 1073741824 < /dev/zero > large-file-of-zeros

./sum-file-bytes
Please Enter name of the File : large-file-of-zeros
sum is : 0; read 1073741824 bytes to reach that sum

答案 1 :(得分:0)

在64位和32位计算机上,有符号整数值范围均为-2,147,483,648 to 2,147,483,647

因此,如果“ {sumdigsig”超过“(正)最大值”,则它将回到负数范围。

让我们考虑一个小例子: 考虑范围是-10到+9

   --->   -10 -9 -8 -7 -6 -5 -4 -3 -2 -1  ----
  |                                           |
   ---    +9 +8 +7 +6 +5 +4 +3 +2 +1  0   <---

考虑a = 4。 因此,如果您执行a = a + 6,即由于超出了范围,它将变为-10。

以相同的方式处理整数,如果该值超过最大值,则它将返回到负数范围。

证明:

#include <stdio.h>

int main()
{
    // a contains the maxium value
    int a = 2,147,483,647;
    a = a + 1; 
    printf("%d", a);
    return 0;
}

输出

-2,147,483,648

建议:与其使用signed-integer,不如使用unsigned Integer。您可以得到更大的射程,即2,147,483,647 + 2,147,483,648