【问题标题】:Why is implicit declaration of gets() not allowed in C99?为什么在 C99 中不允许隐式声明 get()?
【发布时间】:2018-08-21 16:57:56
【问题描述】:

我开始学习 C 语言编程,我所指的代码书显示了一些带有gets() 的源代码,我的 IDLE 也能识别它。但是还是在编译的时候,我的编译器不同意。

谁能帮帮我?我在主函数中使用gets(),并使用clang作为编译器。

【问题讨论】:

  • 可能是因为gets 已被一起删除。您收到的确切错误消息是什么?我很确定这是一个链接器错误。而且从不使用隐式声明,它们是上个世纪遗留下来的。
  • @Mr. Anderson 函数 get 是不安全的,不再被 C 标准支持。改用函数 fgets。你可以在网上找到它的描述。
  • string0.c:8:5: 错误:函数“gets”的隐式声明在 C99 [-Werror,-Wimplicit-function-declaration]gets(s1) 中无效; ^
  • @Mr.Anderson 好的,这实际上是一个编译器错误。显然,您使用的 C 编译器根本不允许隐式声明,这是一件好事。大约 20 年前,gets 函数已被弃用。只是不要使用它。阅读this
  • 三件事。 1:隐式声明只对返回int的函数有效; gets() 返回了char *,所以gets() 的隐式声明无论如何都是错误的。 2: 从 C99 开始,根本不再允许隐式声明。 3:gets() 自 C2011 起已从标准库中删除,因为它危险并且在您的代码中引入故障点。永远不要使用它,即使在玩具代码中也不行。

标签: c clang c99 cs50 gets


【解决方案1】:

如果您尝试调用 my_undeclared_function,您将收到类似“不允许隐式声明获取”的消息,原因与您收到消息“不允许隐式声明 my_undeclared_function”的原因相同。现在,gets 已经不是标准的 C 库函数了。

更详细的解释:在现代 C 中,如果你写

int main()
{
    f();
}

int f()
{
    return 0;
}

您通常会收到类似“函数 'f' 的隐式声明在 C99 中无效”的消息。曾几何时,如果你调用了一个编译器(还)没有听说过的函数,它会假设它会是一个返回 int 的函数,但这个假设在 C99 中被删除了。

另一方面,如果你写

#include <stdio.h>

int main()
{
    char line[100];
    printf("type something:\n");
    fgets(line, sizeof(line), stdin);
    printf("you typed: %s", line);
    return 0;
}

您将不会收到关于函数printffgets 的消息。这些编译器听说过的函数:它们的声明在&lt;stdio.h&gt;

但是如果你写

#include <stdio.h>

int main()
{
    char line[100];
    printf("type something:\n");
    gets(line);
    printf("you typed: %s", line);
    return 0;
}

您将再次收到有关函数gets() 的消息,因为gets 不是编译器听说过的函数。它不是标准功能;它没有在&lt;stdio.h&gt; 中声明。

现在,曾几何时,gets 是一个标准函数,它在 &lt;stdio.h&gt; 中声明,但它是一个非常糟糕和危险的函数,因此它已从标准中删除。您阅读的推荐它的书已经过时了。

【讨论】:

  • 这是不正确的。 gets 只是在 C99 中被标记为过时,并没有从语言中删除。
  • @Lundin 我没有说 gets 已从 C99 的语言中删除。我不确定它是什么时候被移除的,但如果你说它是 C11,我相信你。
【解决方案2】:

扩展我的评论:

首先,永远不要使用gets(),无论出于何种原因,即使是在玩具代码中。如果您在示例程序中看到它,请忽略该示例并继续。它在 C99 中被弃用,并在 C2011 中从标准库中完全删除,因为它是一个主要的安全漏洞。由该功能引起的胃灼热值得打破 30 多年的遗留代码。

其次,在 C89 和更早版本下,如果编译器在看到声明或定义之前看到函数 调用,它将假定函数返回 int - IOW,该函数有一个 隐式声明int。如果您稍后在同一个翻译单元中有一个函数定义,并且该函数返回一个int,那么您很好:

int foo( void )
{
  int x = bar(); // bar *implicitly* declared to return int
}

int bar( void ) // implicit declaration matches definition, we're good
{
  return some_integer_value;
}

但是,如果bar 没有 返回int,您会收到错误,因为隐式int 声明与非int 定义不匹配。

gets() 返回char *,而不是int,因此gets 的隐式声明是不正确的无论如何

C99 完全删除了隐式 int 声明 - 从那时起,所有函数必须在调用之前声明或定义。

编辑

您收到隐式声明错误的最可能原因是您的编译器足够新,以至于它在stdio.h 中不再有gets 的声明。

【讨论】:

    【解决方案3】:

    你没有#include &lt;stdio.h&gt;,就这么简单。

    在 C99 中,如果您使用以下确切代码,则会出现错误:

    int main (void)
    {
      char buf[10];
      gets(buf);
      return 0;
    }
    

    包含 stdio.h 解决了这个问题。尽管值得注意的是,gets 在 C99 中被标记为过时的函数,并在 C11 中完全从语言中删除。所以下面的代码不会在标准C(C11)中编译:

    #include <stdio.h>
    
    int main (void)
    {
      char buf[10];
      gets(buf);
      return 0;
    }
    

    因此,您可能会收到错误,因为您编译为标准 C 而不是 C99。

    (请注意,Windows Mingw 编译器可能使用 C11 编译器,但使用 C99 标准库,因此您可能会得到一些 odd outcomes。)

    详情请见Why is the gets function so dangerous that it should not be used?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-15
      • 1970-01-01
      • 2011-10-05
      • 2012-08-03
      • 2012-03-27
      • 1970-01-01
      相关资源
      最近更新 更多