You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用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()并消除警告(不推荐),可以选择以下方式:

  1. 在代码开头手动添加gets()的函数声明:char *gets(char *buffer);
  2. 编译时指定使用旧版C标准(如-std=c99),同时添加-D__CLIBC_USE(DEPRECATED_GETS)宏定义,让头文件加载gets()的声明。

但强烈建议放弃使用gets(),改用fgets()替代——fgets()可以指定读取的最大长度,从根本上避免缓冲区溢出的安全问题。


内容的提问来源于stack exchange,提问作者Sung-E-gkoght

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:30:59