C操作无符号整数-整数溢出

C操作无符号整数-整数溢出,c,int,integer-overflow,atoi,unsigned-integer,C,Int,Integer Overflow,Atoi,Unsigned Integer,我正在简单C程序中试验无符号int数据类型和主要方法参数。作为一个实验,我编写了一个程序,将命令行中的int数作为main方法的参数,并对该数和0之间的每个整数求和 例如,当n>0时,程序计算f(n)=(1+2+3…+n)有效 #include <stdio.h> #include <stdlib.h> const unsigned int MAX_NUM = 92681; //Max input that will avoid int overflow later o

我正在简单C程序中试验无符号int数据类型和主要方法参数。作为一个实验,我编写了一个程序,将命令行中的int数作为main方法的参数,并对该数和0之间的每个整数求和

例如,当n>0时,程序计算f(n)=(1+2+3…+n)有效

#include <stdio.h>
#include <stdlib.h>

const unsigned int MAX_NUM = 92681; //Max input that will avoid int overflow later on

unsigned int sum(unsigned int x); 

int main(int argc, char *argv[]) { 

    unsigned int input = atoi(argv[1]); 

    if (input < 0 || input > MAX_NUM) {
        printf("Invalid input! Input must be less than 92682\n");
        exit(0); //If input > MAX_NUM, quit program
    }

    unsigned int result = sum(input);

    printf("Sum to %d = %d\n", input, result);

    return 0;
}

unsigned int sum(unsigned int x) {
    unsigned int sum = 0;
    unsigned int y;
    for (y = 0; y <= x; y++) {
        sum += y;
        printf("Current sum:\t%u\n",sum);
    }
    return sum;
}
#包括
#包括
常量无符号整数MAX_NUM=92681//最大输入,可避免以后的int溢出
无符号整数和(无符号整数x);
intmain(intargc,char*argv[]){
无符号整数输入=atoi(argv[1]);
如果(输入<0 | |输入>最大值){
printf(“无效输入!输入必须小于92682\n”);
退出(0);//如果输入>最大值,退出程序
}
无符号整数结果=和(输入);
printf(“求和到%d=%d\n”,输入,结果);
返回0;
}
无符号整数和(无符号整数x){
无符号整数和=0;
无符号整数y;
对于(y=0;y 2147483648-又名有符号整数的最大值)

我手工计算发现,我的程序生成的结果有效的最大值(例如,在整数溢出之前)对于有符号整数为65535,对于无符号整数为92681

运行有符号整数的程序产生了预期的结果——在65535处,由于整数溢出,非常大的正数变成了非常大的负数

然后,我检查并将每个“int”都改为“unsigned int”。尽管如此,整数溢出还是会发生,就好像int是有符号的而不是无符号的一样

我的问题是a)为什么会这样?b)如何使我的答案能够使用整个无符号整数范围,即0到(2^32)-1(因为我不需要负值!)


非常感谢!

您忘记将最终的
printf
格式从已签名更改为未签名

更改:

printf("Sum to %d = %d\n", input, result);
致:


请注意,启用编译器警告(例如,
gcc-Wall…
)会提醒您注意这一点。始终启用编译器警告并始终注意它们。

您忘记将最终的
printf
格式从签名更改为未签名

更改:

printf("Sum to %d = %d\n", input, result);
致:


请注意,启用编译器警告(例如,
gcc-Wall…
)本应提醒您注意这一点。始终启用编译器警告,并始终注意它们。

如果这教会您始终启用编译器警告,那么它将是值得的。;-@PaulR不确定OP使用的是什么,但我希望MSVC最终开始为此发出警告…
/analyze
有点,但速度非常慢d没有警告这种特殊情况(有符号/无符号不匹配)。哦,好吧,至少我们最终会在“14”中得到C99(sn)
printf
version,sigh…;)@user2802841:我没有意识到MSVC在这方面仍然落后,尽管我想我不应该感到惊讶-当然,大多数其他编译器多年来一直在为printf等人生成警告。@user2802841:为了让这些printf警告有用,它们应该考虑到参数是如何生成的。如果
u
类型为
无符号字符
,需要
(无符号)
printf中的cast
是一种愚蠢的迂腐行为,特别是在处理介于两者范围内的值时,非钝实现没有理由不交替处理有符号和无符号类型。如果这教会您始终启用编译器警告,那么这将是值得的。;-@PaulR Not s你知道OP使用的是什么,但我希望MSVC最终会发出警告…
/analyze
有点,但速度非常慢,没有警告这个特殊情况(有符号/无符号不匹配)。哦,好吧,至少我们最终会在“14”中得到C99(sn)
printf
version,sigh…;)@user2802841:我没有意识到MSVC在这方面仍然落后,尽管我想我不应该感到惊讶-当然,大多数其他编译器多年来一直在为printf等人生成警告。@user2802841:为了让这些printf警告有用,它们应该考虑到参数是如何生成的。如果
u
类型为
无符号字符
,则要求在
printf
中强制转换
(无符号)
是愚蠢的迂腐行为,特别是因为没有理由非钝性实现在处理介于两者范围内的值时不交替处理有符号类型和无符号类型。Gauss的提示:n*(n-1)/2.这就是我计算最大值的方式,即2^32=n*(n-1)/2Tip来自高斯:n*(n-1)/2.这就是我计算最大值的方式,即2^32=n*(n-1)/2