在 C 中的 argv[1] 上使用 atoi() 时算术溢出
Posted
技术标签:
【中文标题】在 C 中的 argv[1] 上使用 atoi() 时算术溢出【英文标题】:Arithmetic overflow when using atoi() on argv[1] in C 【发布时间】:2014-02-18 16:59:30 【问题描述】:我正在使用 atoi(argv[1])
这是我的代码的 sn-p
void main(int argc, char* argv[])
int evenOrOdd = 0;
int inputtedNum = 0;
pid_t pid;
int i;
char buf[BUF_SIZE];
if (argc != 2)//make sure user has input correctly entered
printf("Please use input: ./a.out #\n");
else
inputtedNum = atoi(argv[1]);
if(inputtedNum < 0) //make sure number is positive
printf("Please use a positive number.\n");
return;
// ...
代码继续运行等等,但是当输入一些数字时,它有时会认为它们是负数。如果我输入 123456789 它将没有问题并正确运行程序。如果我输入 12345678910 它会认为该数字是负数。我是否在这里遇到了一些缓冲区错误,导致负标志失败?我不太确定如何解决它。
感谢所有帮助!
【问题讨论】:
12345678910
超出了 int32_t 的范围。
您的整数很可能是 32 位,这仅允许它包含最多 2^31-1 的数字。
谢谢约阿希姆。原来这是我的最高数字。
用strtol来检查errno如果你要测试转换结果是否溢出。预计可以输入的范围是多少?
【参考方案1】:
int
是一个比较窄的整数类型,也是一个有符号类型。对inputtedNum
和strtoul(argv[1], 0, 0)
使用unsigned long
来解析数字。
【讨论】:
unsigned long
只会将正数范围从2G增加到4G,所以对于12345678910这样的数字并不能解决问题。
尝试更改为 unsigned long 并使用 strtoul,但并没有像 barak manos 所说的那样工作。
然后查阅手册,发现你可以使用unsigned long long
和strtoull
。如果这不起作用,您的数字对于您计算机上的整数类型来说太大了。【参考方案2】:
在大多数编译器上,C 中支持的最大非负整数类型是 64 位无符号整数。
12345678910 不能存储在您正在使用的int
类型中,即使它是unsigned long
。
您可以通过将argv[1]
中的输入字符串“分割”为两个字符串来解决此问题,当它超过8 位时,在每个字符串上使用atoi
,并将结果组合成一个unsigned long long
变量。
这会将您的正数范围从大约 40 亿扩展到最大的 16 位十进制数字。
来自main
,致电readNum(argv[1])
:
unsigned long long readNum(const char* input)
int length = strlen(input);
if (length <= 8)
return atoi(input);
else if (length <= 16)
char str1[8+1] = 0;
char str2[8+1] = 0;
memcpy(str1,input,8);
memcpy(str2,input+8,length-8);
return 100000000ULL*atoi(str1)+atoi(str2);
return 10000000000000000ULL; // Invalid input
请记住,要打印unsigned long long
,您需要使用printf
和%llu
。
【讨论】:
您的第一个陈述在大多数当前 CPU 上实际上是正确的,但不是标准的正确表征。我怀疑有些 CPUuintmax_t
是 128 位;如果没有,不难想象这样的机器。
嗯,正确。此外,unsigned long
本身在某些编译器上可能是 64 位...不过,我相信当前问题的主要焦点是实际的字符串到数字的转换,而不是 C 中类型的官方标准。所以我选择专注于转换问题的解决方案,而不是根据 C 编译器的标准来关注每种类型的大小。以上是关于在 C 中的 argv[1] 上使用 atoi() 时算术溢出的主要内容,如果未能解决你的问题,请参考以下文章
int main(int argc, char* argv[]) 和线程 1: EXC_BAD_ACCESS (code=1, address=0x0) with atoi(argv[1]);在 Xc
argc atoi argv,Opencv,C++ [关闭]