隐式声明'gets'函数

18

我知道'implicit declaration'通常意味着在调用函数之前必须将函数置于程序顶部,或者我需要声明原型。
然而,gets 应该在 stdio.h 文件中(我已经包含了它)。
有什么方法可以解决这个问题吗?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   char ch, file_name[25];
   FILE *fp;

   printf("Enter the name of file you wish to see\n");
   gets(file_name);
   fp = fopen(file_name,"r"); // read mode
   if( fp == NULL )
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }
}

2
请展示你的代码。 - kaylum
1
你的代码是什么?你是如何编译它的,使用gets的原因是什么? - Petr Skocik
1
请查看http://stackoverflow.com/help/mcve,以获取有关如何生成示例代码的灵感。 - mrhn
2个回答

27

您说得对,如果您包含适当的头文件,就不应该收到隐式声明警告。

然而,从C11标准中移除了 gets() 函数。这意味着在 <stdio.h> 中已经没有 gets() 的原型。曾经,gets()<stdio.h> 中存在过。

移除 gets() 函数的原因是相当出名的:它无法防止缓冲区溢出。因此,您不应该使用 gets(),而应该使用fgets()函数代替,并注意结尾处的换行符,如果有的话。


1
有趣的是,即使它出现错误,它仍然能够正常运行。 - Death_by_Ch0colate
2
这可能是因为库仍然具有该函数,可能是为了避免破坏古老的代码。但是任何新代码都不应该使用 gets() - P.P

17

gets() 已从 C11 标准中移除,请勿使用。

这里有一个简单的替代方法:

#include <stdio.h>
#include <string.h>

char buf[1024];  // or whatever size fits your needs.

if (fgets(buf, sizeof buf, stdin)) {
    buf[strcspn(buf, "\n")] = '\0';
    // handle the input as you would have from gets
} else {
    // handle end of file
}

您可以将此代码封装在一个函数中,并将其用作gets的替代品:

您可以将此代码封装成函数,用其代替gets函数:

char *mygets(char *buf, size_t size) {
    if (buf != NULL && size > 0) {
        if (fgets(buf, size, stdin)) {
            buf[strcspn(buf, "\n")] = '\0';
            return buf;
        }
        *buf = '\0';  /* clear buffer at end of file */
    }
    return NULL;
}

并将它用在你的代码中:

int main(void) {
    char file_name[25];
    FILE *fp;

    printf("Enter the name of file you wish to see\n");
    mygets(file_name, sizeof file_name);
    fp = fopen(file_name, "r"); // read mode
    if (fp == NULL) {
        perror("Error while opening the file.\n");
        exit(EXIT_FAILURE);
    }
}

如果你使用 gets include <stdio.h>,但是像大家所说的那样,你会让你的程序存在缓冲区溢出和利用的风险。只有在测试此函数的漏洞情况时才使用它。 - Samir Ouldsaadi
@chqrlie,sizeof bufsizeof file_name缺少括号吗?为什么需要将大小作为mygets的外部参数,而不是在mygets函数内部执行size=sizeof(buf) - SebMa
@SebMa:只有当sizeof的参数是一个类型时才需要括号。对于表达式,sizeof的行为类似于前缀运算符。我仅在使用sizeof在表达式中时(例如sizeof(*buf) * 10)使用可选的括号,但即使在这个表达式中,括号也是可选和冗余的。 - chqrlie
@SebMa:关于 mygets 函数的 size 参数,它是必需的,因为无法从指针本身确定 buf 所指向的数组的大小。sizeof(buf) 只是指针的大小,而不是数组的大小。 - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接