我开始学习C语言编程,参考的教材中有一些源代码使用了gets()
函数,我的IDLE也能够识别它。但是,在编译时,我的编译器不同意此操作。
有谁能帮我解决这个问题吗?我在主函数中使用了gets()
函数,并使用clang作为编译器。
继续阐述我的评论:
首先,永远不要使用gets()
,即使在玩具代码中也是如此。如果在示例程序中看到它,请忽略该示例并继续执行。它已经在C99中被弃用,并在C2011中从标准库中完全删除,因为它是一个主要的安全漏洞。由于这个函数引起的麻烦值得打破30多年的遗留代码。
其次,在C89及更早版本中,如果编译器在看到声明或定义之前看到函数调用,则会假定函数返回int
- 也就是说,函数具有隐式的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
都是不正确的。int
声明 - 自此之后,所有函数在调用之前必须被声明或定义。
编辑
你收到隐式声明错误的最可能原因是你的编译器足够新,已经没有stdio.h
中的gets
声明。int main()
{
f();
}
int f()
{
return 0;
}
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;
}
你将不会收到有关函数printf
和fgets
的消息。这些是编译器知道的函数:它们的声明在<stdio.h>
中。
但如果您编写:
#include <stdio.h>
int main()
{
char line[100];
printf("type something:\n");
gets(line);
printf("you typed: %s", line);
return 0;
}
gets()
的消息,因为编译器不知道gets
是什么函数。它不是标准函数,也没有在<stdio.h>
中声明。gets
是一个标准函数,并且在<stdio.h>
中声明过,但它是一个极其不合理和危险的函数,因此已从标准中删除。你所阅读的书推荐使用它已经过时了。gets
被标记为过时的,但它并没有从语言中删除。 - Lundingets
在C99中被移除了。我不确定它是在什么时候被移除的,但如果你说是在C11中,我相信你。 - Steve Summit你没有包含 #include <stdio.h>
,就是这么简单。
在 C99 中,如果你使用这个确切的代码,你会得到一个错误:
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
gets
被标记为过时函数,并在 C11 中完全从语言中删除。因此,以下代码将无法在标准 C(C11)中编译:#include <stdio.h>
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
你可能会因为编译成标准 C 而不是 C99 而出错。
(注意,Windows Mingw 编译器特别可能使用 C11 编译器但是使用 C99 标准库,因此你可能会在使用它时得到一些奇怪的结果。)
请参见“gets” 函数为什么如此危险? 了解详情。
gets
函数已经完全移除了。你收到的错误消息是什么?我很确定这是一个链接器错误。而且 永远不要 使用隐式声明,它们是上个世纪遗留下来的东西。 - Jabberwockygets
函数已经被废弃了大约20年。不要使用它。请阅读this。 - Jabberwockygets()
返回char *
,因此隐式声明gets()
是错误的。2:自C99起,不再允许隐式声明。3:自C2011起,标准库中已删除了gets()
,因为它是危险的,并且会在您的代码中引入故障点。永远不要使用它,即使是在玩具代码中也不行。 - John Bode