【问题标题】:implicit declaration of function ‘getline’ warning thrown in one code, but not in another在一个代码中抛出函数“getline”警告的隐式声明,但在另一个代码中没有
【发布时间】:2021-05-03 14:38:47
【问题描述】:

这个问题不是如何删除警告

我正在写一个shell。我提到了这个source。我在我的代码中使用了与他一样的标题(以相同的顺序)。

编译他的代码时,我没有收到关于getline隐式声明 的任何警告。但是当我编译我的时,它确实被抛出了。

手册页建议使用#define _GNU_SOURCE,并添加它从我的代码中删除了警告。

那么为什么博客中的代码没有发出警告,因为他没有使用#define _GNU_SOURCE


这是最少的代码(我复制了上面提到的所有标题)

// #define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
  ssize_t bytes_read;
  size_t input_buffer_size = 1024;
  char *user_input = (char *)malloc(input_buffer_size * sizeof(char));

  while (1)
  {
    printf("> ");
    bytes_read = getline(&user_input, &input_buffer_size, stdin);

    printf("%s\n", user_input);
  }

  return 0;
}

这是我使用的编译过程...

gcc -std=c11 -o bin/shell src/shell.c

如果我将第一行注释掉,则会出现以下错误。

src/shell.c: In function ‘main’:
src/shell.c:18:18: warning: implicit declaration of function ‘getline’ [-Wimplicit-function-declaration]
   18 |     bytes_read = getline(&user_input, &input_buffer_size, stdin);
      |                  ^~~~~~~

【问题讨论】:

  • 可能使用了不同版本的编译器。
  • 你的代码有什么不同?
  • 在收到警告时您使用了哪些命令行参数?另外,cc --version | head -n1 打印什么?
  • 显示代码 (minimal reproducible example),因为它是在问题正文中
  • 有一个非标准函数getline,不符合标准的编译器可能会喷入标准头文件。如果您尝试编写自己的名为getline 的函数,则必须通过例如gcc -std=c11 -pedantic-errors 来阻止库之一的存在。或者,如果要使用预制的getline,则需要使用非标准库gcc -std=gnu11进行编译。

标签: c input getline


【解决方案1】:

您所指的教程编写者在测试代码时似乎没有提供任何特殊的编译选项。我在该页面的任何地方只看到一个编译命令,它是gcc -o main main.c。因此,他们获得了 GCC 的默认值,这通常使getline 在拥有它的计算机上可用。

但是,您在编译代码时使用了编译器标志 -std=c11。该标志的作用之一是 GCC 指示 C 库的头文件声明 ISO C2011 指定的函数、常量、变量等。 (取决于您使用的 C 库,该指令可能有也可能没有任何效果——但 Ubuntu 使用 GNU C 库,它彻底实现了它。)getline 不是 ISO C2011 的一部分,所以它没有被声明当你尝试使用它时,你会得到一个“隐式声明”诊断。

使用超一致性-std=cXX 模式几乎总是一个错误。-std=cXX-std=gnuXX 之间恰好有三个区别,并且在实践中它们都不是可取的:

  1. 如上所述,它指示标头不要声明任何不属于 ISO C 指定版本的任何内容。正如您自己所见,在编写重要的 C 程序时,这几乎不是您想要的。它还具有破坏库头文件(包括第三方头文件和 C 库自己的头文件)的令人讨厌的趋势,因为它们很少(如果有的话)在这种模式下进行测试。

  2. 它会禁用污染用户命名空间的“system-specific predefined macros”(例如linuxunixarm)。这在抽象上是可取的,但与 #1 一样,有一种令人讨厌的趋势,即破坏在这种模式下很少(如果有的话)测试的库头。

  3. 启用 trigraphs,这是使 C 与缺少一些标点符号的 ASCII 的“国家变体”一起工作的一个组合。这些很少使用,并造成如此多的实际混乱,以至于它们实际上已从 C++ 2017(不是 C 2017)中删除。

要编译您自己的代码,具有相当挑剔的一致性诊断水平,但又不冒破坏库头的风险,有更好的选项组合:

cc -std=gnuXX -g -Og -Wall -Wextra -Wpedantic -Wstrict-prototypes -Wwrite-strings

(选择一个合适的 XX;如果您没有理由选择其他任何东西,我会选择 11。)您可能想要也可能不想为 _xxx_SOURCE feature selection macros 之一添加 -D 开关;解释这些是如何工作的以及如何选择一个本身就是一个完整的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 2021-12-27
    • 2012-01-16
    相关资源
    最近更新 更多