【问题标题】:Why can I use gets() in gcc -std=c11?为什么我可以在 gcc -std=c11 中使用gets()?
【发布时间】:2015-08-17 15:28:06
【问题描述】:

gets() 函数已从 C 语言中删除。标准中不存在这样的功能。

但我编译了以下代码:

#include <stdio.h>

int main (void)
{
  (void) gets (NULL);
}

使用

gcc -std=c11 -pedantic-errors -Wall -Wextra

它编译时不会给出任何错误或警告。同样,

#include <stdio.h>

int gets;

int main (void)
{}

不会编译(错误:“gets”被重新声明为不同类型的符号)。

在标准 4.Conformance §6 中,我们可以阅读:

符合标准的实现可能有扩展(包括额外的 库函数),只要它们不改变任何 严格符合程序

鉴于上述情况,我认为 gcc 不符合标准,即使在迂腐模式下也是如此。是否有一个原因?这是故意的还是错误的?

GCC 版本 4.9.1。

编辑:

gcc --version
gcc (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 4.9.1

【问题讨论】:

  • GCC 4.8.2 在这里。在迂腐模式下,第一个 sn-p 不会编译,因为从未定义过 gets。在非迂腐模式下,我得到warning: the `gets' function is dangerous and should not be used.。第二个 sn-p 不是问题,因为没有什么可以阻止您声明一个名为 gets 的符号。例如,int printf; 是完全合法的。我错过了问题的重点吗?
  • 我支持 gcc 4.9.1 特有的错误,因为版本 4.8.2 和 > 4.9.2 确实失败了。
  • MinGW 使用微软的标准库,甚至不能正确支持 C99。
  • @hacks:不,gcc 从未支持过gets -- 或fgets。如果给定实现支持gets,则它由库实现,而不是由编译器实现。
  • @hacks:是也不是。在 GNU C 库提供的 &lt;stdio.h&gt; 头文件中,gets 仍然被声明,但声明被 #if !defined __USE_ISOC1 ... #endif 包围。 实现仍然存在,但允许用户代码定义具有相同名称的函数。

标签: c gcc language-lawyer c11 gets


【解决方案1】:

gcc 只是编译器,而不是整个实现。

在我的系统(Linux Mint 17.3、gcc 4.8.4、GNU libc 2.19)上,我得到:

$ gcc -std=c11 -pedantic-errors -Wall -Wextra -c c.c
c.c: In function ‘main’:
c.c:5:3: error: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]
   (void) gets (NULL);
   ^

要正确诊断错误,实现需要符合要求。这意味着编译器(一开始从未提供过gets)和库。

您使用的库仍然提供gets 函数。因此,实现作为一个整体(由编译器 gcc、库和其他一些部分组成)不符合 C11。

底线:这不是 gcc 问题,gcc 对此无能为力。 (嗯,它可以gets 发出一个特殊情况诊断,但它必须确定它不是对同名用户定义函数的有效调用。)

【讨论】:

  • 虽然 C 标准库已弃用 gets,但 GNU C 库仍然包含此功能。
  • 复制我对您其他评论的回复:@hacks:是和否。在 GNU C 库提供的 头文件中,gets 仍然被声明,但声明被 #if !defined __USE_ISOC1 ... #endif 包围。实现仍然存在,但允许用户代码定义具有相同名称的函数。
  • 好的。你认为这是一个错误吗?
  • @hacks:这个特定的实现 (MinGW) 未能符合 C11 标准。 (另请参阅 MinGW 的 long double 问题,适用于 C90、C99 和 C11。)当然,我会说这是一个错误。 (但这是一个很容易避免的——不要使用gets,即使你的编译器没有警告你。)
  • 感谢您的指正。我很高兴你在差不多一年后来到这篇文章(有点惊讶!!)来分享这些信息。
【解决方案2】:

您的代码的关键行是:

#include <stdio.h>

您是否更新了系统的 C 库和头文件?它们与编译器一起也是 C 实现的一部分。

【讨论】:

  • 我确实运行了mingw-get updatemingw-get upgrade,之后出现同样的错误。
  • 正如 Andrew 所提到的,关键行是#include 。您应该找到并分析 gcc 用于执行编译的 stdio.h 文件。该文件可能仍然定义了gets函数。
【解决方案3】:

更新这可能不是问题的答案,我试着让它提供信息。

我碰巧发现提到 gets 的 gcc 对于某些库问题 glibc 2.16 没有遵循 C11 标准。

查看C11的gcc支持状态:https://gcc.gnu.org/wiki/C11Status

但是我找不到“库问题”的定义和其他版本的 glibc 的当前状态。

所以我在我的机器 ubuntu16.04 上尝试了 gcc 版本5.3.1 20160413,glibc 版本Ubuntu GLIBC 2.23 我们可以在编译时得到足够的警告,但执行输出对象文件以实现“向后兼容性”仍然可以。

warning: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]
warning: the `gets' function is dangerous and should not be used.

【讨论】:

  • 这是误导。 gcc 没有删除gets,因为gcc 从一开始就没有提供gets。它由库提供,而不是由编译器提供(这就是为什么该状态页面将其称为“库问题”)。
  • @Keith Thompson。感谢您的回答!这是惊人的清晰和有用:)。
猜你喜欢
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 2010-12-23
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
相关资源
最近更新 更多