C atoi&x2014;如何识别零和误差之间的差异?
返回值 成功时,函数将转换后的整数作为C atoi&x2014;如何识别零和误差之间的差异?,c,atoi,C,Atoi,返回值 成功时,函数将转换后的整数作为int值返回。 如果无法执行有效转换,则返回零值。 如果正确的值超出可表示值的范围,则返回INT_MAX或INT_MIN 那么我如何区分atoi(“poop”)和atoi(“0”)和atoi(“0000000”) 是的,我可以循环检查所有的零,以防我得到0的结果,但是没有更好的方法吗 注意:我使用ANSI C89这是atoi有时被认为不安全的原因之一。改用strtol/strtoul。如果你有,就用它 函数atoi比您想象的更危险。说: 如果无法表示该值,则
int
值返回。
如果无法执行有效转换,则返回零值。
如果正确的值超出可表示值的范围,则返回INT_MAX或INT_MIN
那么我如何区分atoi(“poop”)
和atoi(“0”)
和atoi(“0000000”)
是的,我可以循环检查所有的零,以防我得到0的结果,但是没有更好的方法吗
注意:我使用ANSI C89这是
atoi
有时被认为不安全的原因之一。改用strtol
/strtoul
。如果你有,就用它
函数atoi
比您想象的更危险。说:
如果无法表示该值,则行为未定义
C99标准还规定:
7.20.1
函数atof、atoi、atol和atol不必影响
整数表达式errno出现错误。如果结果的值为
无法表示,行为未定义
你不能
atoi
无法检测错误。如果结果无法表示,atoi
调用未定义的行为。使用strtol
而不是atoi
安全证书编码建议使用strtol
而不是atoi
,内容如下:
如@cnicutar和@ouah所述,
atoi
无法区分有效的0和无效的字符串,从而使strtol
系列成为更好的选项
但是为什么?和如何?首先要了解atoi
和strtol
都只将字符串中的初始数字集转换为数值。任何尾随的非数字字符都将被忽略strtol
可用于检查无效字符串,因为除了数值外,它还返回指向字符串数值部分末尾的指针。因此,如果此end
指针仍然指向原始字符串的开头,则可以判断出有错误,并且没有转换字符串中的任何字符
如代码示例所示,还有一些其他微妙之处:
long lnum;
int num;
char *end;
errno = 0;
lnum = strtol(in_str, &end, 10); //10 specifies base-10
if (end == in_str) //if no characters were converted these pointers are equal
fprintf(stderr, "ERROR: can't convert string to number\n");
//If sizeof(int) == sizeof(long), we have to explicitly check for overflows
if ((lnum == LONG_MAX || lnum == LONG_MIN) && errno == ERANGE)
fprintf(stderr, "ERROR: number out of range for LONG\n");
//Because strtol produces a long, check for overflow
if ( (lnum > INT_MAX) || (lnum < INT_MIN) )
fprintf(stderr, "ERROR: number out of range for INT\n");
//Finally convert the result to a plain int (if that's what you want)
num = (int) lnum;
长lnum;
int-num;
字符*结束;
errno=0;
lnum=strtol(in_str,&end,10)//10指定基-10
if(end==in_str)//如果未转换任何字符,则这些指针相等
fprintf(stderr,“错误:无法将字符串转换为数字\n”);
//如果sizeof(int)=sizeof(long),我们必须显式地检查溢出
如果((lnum==LONG_MAX | | lnum==LONG_MIN)&&errno==ERANGE)
fprintf(stderr,“错误:数字超出长\n范围”);
//因为strtol会产生一个长的检查溢出
如果((lnum>INT_MAX)| |(lnum
注意:如果您确定输入字符串将在有效的int范围内,您可以消除
lnum
并直接强制转换strtol的返回值:num=(int)strtolen(in_str,&end,10)
关于atoi
,它根本不检测错误。不要信任该站点。当正确的值超出范围时,atoi()
返回的值不在C89、C99和C11标准中。C++11标准说的更少(它在两个表中列出了atoi
,仅此而已!)。来自的声明本质上是一厢情愿的想法和/或常见的实现——没有任何standard.TL的保证;DR:改用。这有很多好处,但是……如果sizeof(int)==sizeof(long)
,您就没有检测到溢出。您应该设置errno=0在调用strtol()
之前,您需要测试((lnum==LONG_MAX | | lnum==LONG_MIN)和&errno==ERANGE)以发现溢出。尽管它可以完成这项工作,strtol()
实际上很难正确使用,甚至比您演示的还要难。@JonathanLeffler说得很好。我已经相应地更新了我的答案,谢谢。关于if((lnum>INT_MAX)|(lnum
,对于long
溢出的对称性,if()
块也应该errno=ERANGE编码>并将lnum
设置为INT\u MAX
或INT\u MIN
。不回答标题问题。