C语言中 "atoi" 和 "strtol" 的用法区别

6

自一年前起我一直在使用atoi,最近几天我遇到了一个问题:表达式 atoi("20")输出0。后来我通过谷歌了解到,atoi已经被弃用,应该使用strtol。有趣的是,我了解到atoi内部使用的是strtol。那么,当我把它改成strtol时,问题怎样得以解决呢?


5
atoi仍然有效。atoi("20")应该返回20。问题出在您没有展示的代码中。[编辑]您的问题并展示一个[mcve]。另外,请阅读此:[ask] - Jabberwocky
2
请提供一个最小可重现的示例。atoi()函数可能已被弃用,但它仍然可以正常工作:示例 - Felix G
3
@SaitejaPabisetti,atoi是否使用strtol并不重要。atoi只做文档中所说的事情,不多也不少。错误在于_你的代码_。也许atoi对你的使用太过有限,如果没有看到一些源代码,我们就无法知道。 - Jabberwocky
2
atoi 已经使用了几十年。如果在程序的某个时刻 atoi("20") 返回 0,那么这只是一个证明,在程序的任何地方都存在未定义行为。C 是一种低级语言,未定义行为的后果不一定是局部的。这甚至是它被称为“未定义行为”的原因... - Serge Ballesta
3
一旦您提供相关的代码,我认为问题将会立即解决。我真的怀疑您的程序中是否有带有文字字符串的atoi("20")。更可能是stoi(str),您认为str应该是"20",但没有检查。您的评论“在第一次迭代中它可以工作,在第二次迭代中它就不起作用了”表明问题出在您的代码中。 - M Oehm
显示剩余9条评论
3个回答

7

man页面中的解释:

atoi()函数将nptr指向的字符串的初始部分转换为int。其行为与以下内容相同:

strtol(nptr, NULL, 10);

除了atoi()不会检测错误。atol()和atoll()函数的行为与atoi()相同,只是它们将字符串的初始部分转换为它们的返回类型long或long long。

有关更多信息,请参见此主题中两个函数之间的差异:atoi - strtol


3
根据数据的不同,strtol() 具有更强的功能。
int easy = atoi(data);
// no errors detected

char *err;
errno = 0;
long tmp = strtol(data, &err, 10);
if (errno) /* deal with errno: overflow? */;
if (tmp > INT_MAX) /* int overflow */;
if (tmp < INT_MIN) /* int "underflow" */;
if (*err) /* extra data */;
int comprehensive = tmp; // convert from long

0
除了 pmg 给出的 这个答案,解释了 strto... 具有更多的功能和错误检查之外,ato... 函数被标准保证行为如下(C17 7.22.1.2):

Except for the behavior on error, they are equivalent to

atoi:  (int)strtol(nptr, (char **)NULL, 10)
atol:  strtol(nptr, (char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)

话虽如此,ato...在内部不需要调用strto...(尽管这在许多库中是这种情况),只需表现出相同的行为即可,除了错误处理。

请注意,ato...函数尚未正式列为过时。但仍应避免使用它们,主要是因为使用atoi是毫无意义的,我们可以使用strtol(str,NULL,10),后者与前者相同但具有更好的错误处理能力。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接