为什么C99中不允许gets()的隐式声明?

为什么C99中不允许gets()的隐式声明?,c,clang,c99,cs50,gets,C,Clang,C99,Cs50,Gets,我开始学习用C语言编程。我参考的《代码》一书展示了一些带有gets()的源代码,我的IDLE也认识到了这一点。但是在编译它的时候,我的编译器还是不同意 有人能帮我吗?我在主函数中使用gets(),并使用clang作为编译器。您会收到类似“不允许隐式声明gets”的消息,原因与您在尝试调用my_undeclared_函数时会收到“不允许隐式声明my_undeclared_函数”的消息相同。现在,get不是标准的C库函数 更详细地解释:在现代C语言中,如果 int main() { f();

我开始学习用C语言编程。我参考的《代码》一书展示了一些带有
gets()
的源代码,我的IDLE也认识到了这一点。但是在编译它的时候,我的编译器还是不同意


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

您会收到类似“不允许隐式声明gets”的消息,原因与您在尝试调用
my_undeclared_函数时会收到“不允许隐式声明my_undeclared_函数”的消息相同。现在,
get
不是标准的C库函数

更详细地解释:在现代C语言中,如果

int main()
{
    f();
}

int f()
{
    return 0;
}
#include <stdio.h>

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

int main()
{
    char line[100];
    printf("type something:\n");
    gets(line);
    printf("you typed: %s", line);
    return 0;
}
您通常会收到类似“函数“f”的隐式声明在C99中无效”的消息。曾几何时,如果你调用了一个编译器还没有听说过的函数,它会假设它是一个返回
int
的函数,但是这个假设在C99中被删除了

另一方面,如果你写

int main()
{
    f();
}

int f()
{
    return 0;
}
#include <stdio.h>

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

int main()
{
    char line[100];
    printf("type something:\n");
    gets(line);
    printf("you typed: %s", line);
    return 0;
}
您将再次收到有关函数
gets()
的消息,因为
gets
不是编译器听说过的函数。它不是一个标准函数;它未在
中声明


现在,曾几何时,
get
是一个标准函数,它在
中声明,但它是一个极其糟糕且危险的函数,因此已从标准中删除。你推荐这本书的那本书已经过时了。

继续我的评论:

首先,不要出于任何原因使用
get()
,即使是在玩具代码中。如果您在示例程序中看到它,请忽略该示例并继续。它在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
中声明
get

你没有包含
,就这么简单

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

int main (void)
{
  char buf[10];
  gets(buf);
  return 0;
}
包括stdio.h解决了这个问题。尽管值得注意,
gets
在C99中被标记为一个过时的函数,并且在C11中完全从语言中删除。因此,以下代码不会在标准C(C11)中编译:

#包括
内部主(空)
{
char-buf[10];
获取(buf);
返回0;
}
因此,您可能会得到错误,因为您编译为标准C而不是C99

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


有关详细信息,请参阅。

可能是因为
获取
已全部删除。您得到的确切错误消息是什么?我很确定这是链接器的错误。不要使用隐式声明,它们是上个世纪遗留下来的。@Anderson先生,函数get是不安全的,C标准不再支持它。改用函数fgets。您可以在internet中找到它的描述。string0.c:8:5:错误:函数“gets”的隐式声明在C99[-Werror,-Wimplicit函数声明]gets(s1)中无效^@安德森先生,好的,这实际上是一个编译器错误。显然,您使用的C编译器根本不允许隐式声明,这是一件好事。
get
函数在大约20年前就被弃用了。不要用它。读三件事。1:隐式声明仅对返回
int
的函数有效
gets()
返回了
char*
,因此
gets()
的隐式声明是错误的。2:从C99开始,隐式声明不再被允许。3:
gets()
从C2011起已从标准库中删除,因为它很危险,会在代码中引入故障点。永远不要使用它,即使是在玩具代码中。这是不正确的
gets
只是在C99中被标记为过时,它没有从该语言中删除。@Lundin我没有说在C99中,
gets
已从该语言中删除。我不确定它是什么时候被移除的,但如果你说它是C11,我相信你。