为什么 gets() 假设 extern 在 C 代码中返回 int?

Why does gets() assuming extern returning int in this code in C?

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

int main() {
    int length;
    char **lines, buffer[80];

    printf("How many lines do you want to enter?.\n");
    scanf("%d", &length);
    getchar();
    lines = (char**)malloc(length * sizeof(char*));
    for (i = 0; i < length; ++i) { //Scan user's lines
        gets(buffer);
        lines[i] = (char*)malloc(strlen(buffer) * sizeof(char) + 1);
        if (!lines[i]) { //Check if allocation available
            printf("Error! Out of memory!");
            return endProgram;
        }
        strcpy(lines[i], buffer);
    }
    return 0;
}

我想知道为什么 gets() 函数会给我一个假设 extern 返回 int 的错误,我只是想扫描一个字符串。

最有可能的原因是 gets() function has been deprecated 有一段时间了。它似乎已从您系统上的 <stdio.h> 中删除。

幸运的是,这种情况很容易解决:将调用替换为 fgets(),如下所示:

fgets(buffer, sizeof(buffer), stdin);

注意: fgets 不是 drop-in gets 的替代品,因为它在 returns 所在的字符串的行尾保留 '\n' 个字符。 Q&A 讨论了这个问题,并提供了解决方案。

gets() 函数已从 C 标准中删除。它从来都不是一个好用的函数,因为无法告诉 gets 参数缓冲区有多大,如果输入文件来自不受信任的来源,很容易导致缓冲区溢出甚至恶意攻击。您的编译器抱怨 assuming extern 返回 int 的原因是 gets 的原型不再出现在您的 <stdio.h> 系统头文件中。

这样修改你的代码:

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

int main(void) {
    int length;
    char **lines, buffer[81];

    printf("How many lines do you want to enter?.\n");
    if (scanf("%d", &length) != 1)
        return 1;
    getchar();  // consuming the line feed typed by the user.
    lines = malloc(length * sizeof(char*));
    if (lines == NULL) {
        printf("Error! Out of memory!\n");
        return 2;
    }
    for (i = 0; i < length; i++) { //Scan user's lines
        if (!fgets(buffer, sizeof buffer, stdin)) {
            printf("Error! Premature end of file!\n");
            return 2;
        }
        buffer[strcspn(buffer, "\n")] = '[=10=]'; // overwrite the final \n
        lines[i] = strdup(buffer);
        if (lines[i] == NULL) {
            printf("Error! Out of memory!\n");
            return 2;
        }
    }
    // perform other work on the buffer.
    return 0;
}

gets() 在 C99 中被弃用,并从 C11 的标准 C 中删除。

OP 收到警告 "about assuming extern returning int" 因为它不是标准包含文件中的原型。

要用其他东西替换 gets() 大约可以用 fgets()

使用新代码,使用 fgets() 及其怪癖。


要滚动自己的 my_gets(char *dest, size_t size),与前 gets() 高度兼容,代码应该:

  1. 取一个与目标数组大小匹配的大小参数。

  2. 在为目标数组读取太多字符后,my_gets() 可以自由执行任何合理的功能,因为前者 gets() 此时会导致未定义的行为。建议尽可能填充数组,消耗字符直到'\n'EOF,并返回NULL表示错误(可能设置errno)。

  3. fgets() 的简单使用是有问题的,因为传递给 fgets() 的大小是字符的 space,'\n''[= 25=]',而传递给 my_gets() 的大小实际上应该是字符和 '[=25=]' 所需的 space。 '\n' 正在消耗且未保存。

使用 VLA 满足这些目标的候选函数位于 。