为啥我在 c 中遇到 atoi 的段错误?
Posted
技术标签:
【中文标题】为啥我在 c 中遇到 atoi 的段错误?【英文标题】:Why do I get a segfault with atoi in c?为什么我在 c 中遇到 atoi 的段错误? 【发布时间】:2020-12-10 10:27:46 【问题描述】:我正在尝试从 argv 读取字符串。它应该类似于 "-x^2-5"
等数学函数。
我有这样的东西:
void test(char *function)
int temp = 0;
for (int i = 0; i < strlen(function); i++)
if((function[i] != '+') && (function[i] != ...)
// function[i] is a digit, but still as a char
temp = atoi(function[i]);
//...
int main(int argc, char **argv)
test(argv[1]);
//...
这在循环的最后一圈之前运行良好。
如果我使用printf("%c", function[i]);
,它就是5
。
但是atoi(function[i])
给出了段错误。为什么?
【问题讨论】:
请在使用argv[1]
之前测试if(argc >= 2)
。
打开编译器警告! function[i]
是单个 char
,而不是 char*
。因此,它被隐式转换为指针类型,atoi
尝试从接近零的内存地址读取。也许你的意思是&function[i]
或function + i
atoi(function[i])
实际上是无效的 C,所以无论编译器让这段代码通过什么都是不好的。请注意,大多数主流 C 编译器默认情况下都处于“不良模式”。您必须添加 -std=c11 -pedantic-errors
才能将它们转换为 C 编译器。另请参阅“Pointer from integer/integer from pointer without a cast” issues。
【参考方案1】:
没错。我们先来看看atoi
的签名。
int atoi(const char *str);
现在,您传递给它的是function[i]
,因为function
是char *
类型,function[i]
是char
。而且您的角色很可能不是正确的角色指针。
您想要传递给atoi
的是const char *
,您可以通过调用atoi(&function[i]);
得到它
【讨论】:
@xXxKaddiexXx 虽然如果我试图解析这样的表达式,我会考虑对表达式进行“适当”的词法分析,然后使用“分流场”算法来创建一个用户提供的表达式中的表达式树。更容易识别符号是运算符、变量(如 x)还是文字值(如 2)。也更容易评估。【参考方案2】:正如@sham1 所说,atoi
期望它的参数是一个 C 字符串,这是一个以 null 结尾的 char 数组,而您只有一个 char。
但是数字是特殊的,因为它们需要有连续的代码。所以如果你知道一个字符(比如c
)是一个数字,它的值就是c - '0'
。所以你可以写:
if((function[i] != '+') && (function[i] != ...)
// function[i] is a digit, but still as a char
temp = function[i] - '0'; // get the int value of a digit character
【讨论】:
实际上这在我的情况下不起作用。我不确定我是否错过了上面代码示例中的重要内容。【参考方案3】:除了其他答案中指出的错误之外,atoi
没有任何可靠的错误处理,这就是为什么它是standard library functions that should never be used 之一。
忘记您曾经听说过atoi
并将其替换为:
char* endptr;
int result = strtol(str,&endptr,10);
if(endptr == str)
// some conversion error
strtol
也可以转换字符串的初始部分,如果它包含有效数字。
【讨论】:
哦不,我不知道。那会节省很多时间xD。谢谢你:) @xXxKaddiexXx 在这种特定情况下,您实际上提供的内容不是以 null 结尾的字符串,因此strtol
也不太可能找到这个问题。以上是关于为啥我在 c 中遇到 atoi 的段错误?的主要内容,如果未能解决你的问题,请参考以下文章