为何使用gets()赋值会触发‘char*与int类型不匹配’gcc警告?
关于gets()函数编译警告的疑问及解析
问题场景
我正在学习C语言,遇到一个困惑的问题:我知道gets()的返回值是char*,函数声明为char * gets(char *buffer),但编写以下代码时,gcc却抛出类型不匹配的警告:
#include <stdio.h> int main(void) { char str[20], *p; p = gets(str); /* <- gcc提示警告: assignment ~. */ }
警告内容为:
assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
明明p和gets()的返回值都是char*类型,为什么会出现这个警告?程序能正常运行,但我希望编译时没有任何提示。
问题原因
这背后的核心原因是隐式声明导致的返回值默认类型问题:
gets()函数在C11标准中已经被正式移除,现代C标准库的头文件默认不会暴露它的声明。- 虽然该函数仍存在于系统库中,但当编译器找不到它的显式声明时,会按照C语言的旧规则,默认认为该函数的返回值是
int类型。 - 这就导致了代码中
char*类型的p被赋值为int类型的隐式返回值,触发了类型不匹配的警告。
另外需要注意:gets()本身是极不安全的函数,它不检查输入长度,很容易造成缓冲区溢出,现在推荐使用fgets()作为替代方案。
gets()在头文件中的存在形式
头文件中gets()的声明被条件编译包裹,只有在启用特定宏时才会暴露:
#if __CLIBC_USE (DEPRECATED_GETS) /* Get a newline-terminated string from stdin, removing the newline. This function is impossible to use safely. It has been officially removed from ISO c11 and ISO c++14, and we have also removed it from the _GNU_SOURCE feature list. It remains available when explicitly using an old ISO C, Unix, or POSIX standard. This function is a possible cancellation point and therefore not marked with __THROW. */ extern char *gets (char *__s) __wur __attribute_deprecated__; #endif
这段代码的含义是:只有当定义了__CLIBC_USE(DEPRECATED_GETS)宏时,才会包含gets()的声明,同时还通过__attribute_deprecated__标记该函数为已废弃。
消除编译警告的方案
如果一定要使用gets()并消除警告(不推荐),可以选择以下方式:
- 在代码开头手动添加
gets()的函数声明:char *gets(char *buffer); - 编译时指定使用旧版C标准(如
-std=c99),同时添加-D__CLIBC_USE(DEPRECATED_GETS)宏定义,让头文件加载gets()的声明。
但强烈建议放弃使用gets(),改用fgets()替代——fgets()可以指定读取的最大长度,从根本上避免缓冲区溢出的安全问题。
内容的提问来源于stack exchange,提问作者Sung-E-gkoght
相关产品推荐
相关产品推荐

