使用strtok_r分割字符串时编译报错,请求排查问题原因
编译strtok_r代码时的错误原因解析
问题背景
根据strtok_r手册页的说明:
返回值
strtok()和strtok_r()函数返回指向下一个标记的指针,若无更多标记则返回NULL。
我编写了一个以空格、制表符和换行符为分隔符的字符串分割函数,代码如下:
#include "program.h" #include <string.h> /** * tokenize_line - Tokenize command input plus any other arguments * @s: line to parse * @tokens: buffer for filling * * Return: 1 if success, 0 for failure */ int tokenize_line(char *s, char *tokens[]) { int i, status; char *token, *hold; token = strtok_r(s, " \t\n", &hold); status = check_if_comment(&token); if (status == 1) return (0); for (i = 0; token && i < 2; i++) { tokens[i] = token; token = strtok_r(NULL, " \t\n", &hold); } return (1); }
使用编译命令:gcc -Wall -Werror -Wextra -pedantic -std=c89 filename_with_this_function.c时,出现以下编译错误:
In function ‘tokenize_line’: error: implicit declaration of function ‘strtok_r’; did you mean ‘strtok’? [-Werror=implicit-function-de claration] 15 | token = strtok_r(s, " \t\n", &hold); | ^~~~~~~~ | strtok error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversio n] 15 | token = strtok_r(s, " \t\n", &hold); | ^ error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversio n] 24 | token = strtok_r(NULL, " \t\n", &hold); | ^
错误原因
这三个错误的核心根源是**strtok_r不属于C89标准库**:
- 编译时指定了
-std=c89,强制编译器严格遵循C89标准。而strtok_r是POSIX标准定义的线程安全版字符串分割函数,并未被纳入C89标准。此时编译器无法从<string.h>中找到strtok_r的函数声明,因此触发“隐式函数声明”的错误。 - 在C语言旧规则中,编译器遇到未声明的函数时,会默认假设该函数返回
int类型。但你将这个被默认视为int的返回值赋值给了char*类型的变量token,这就导致了“将int赋值给char*”的类型不匹配错误,也就是后面两个报错的直接原因。
解决方向
你可以根据需求选择以下两种方案:
- 修改编译选项:去掉
-std=c89,改用-std=gnu89(该选项在C89基础上包含了GNU扩展和POSIX兼容函数),这样编译器就能识别strtok_r的声明。 - 替换函数:如果必须严格遵循C89标准,将
strtok_r替换为C89标准中的strtok函数,但要注意strtok是线程不安全的,使用时需要处理好全局状态的问题。
内容的提问来源于stack exchange,提问作者greez'
相关产品推荐
相关产品推荐

