在一个代码中抛出函数“getline”警告的隐式声明,但在另一个代码中不抛出
implicit declaration of function ‘getline’ warning thrown in one code, but not in another
这个问题不是如何删除警告
我正在写一个shell。我提到了这个 source。我在我的代码中使用了与他相同的 headers(顺序相同)。
编译他的代码时,我没有收到任何关于 getline
的 隐式声明 的警告。但是当我编译我的时,它确实被抛出。
手册页建议使用 #define _GNU_SOURCE
,并添加它从我的代码中删除了警告。
那么为什么博客中的代码没有抛出警告,因为他没有使用#define _GNU_SOURCE
?
这是最简单的代码(我复制了上面提到的所有 headers)
// #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);
| ^~~~~~~
您提到的教程的编写者似乎在测试代码时没有提供任何特殊的编译选项。我在那个页面的任何地方只看到一个编译命令,它是 gcc -o main main.c
。因此,他们获得了 GCC 的默认值,通常,这使得 getline
在拥有它的计算机上可用。
但是,您在编译代码时使用了编译器标志 -std=c11
。这个标志的作用之一是GCC指示C库的headers只声明ISO C2011规定的函数、常量、变量等。 (根据您使用的 C 库,此指令可能有也可能没有任何效果 — 但 Ubuntu 使用 GNU C 库,它彻底实现了它。)getline
不是 ISO C2011 的一部分,所以它没有被声明,当你尝试使用它时你会得到一个“隐式声明”诊断。
使用超一致性 -std=cXX
模式几乎总是错误的。 -std=cXX
和 -std=gnuXX
和 none 在实践中是可取的:
如上所述,它指示 headers 不要声明任何不属于 ISO C 指定修订版的内容。正如您亲眼所见,这几乎不是您想要的在编写一个重要的 C 程序时。它也有破坏库 headers 的严重倾向——包括 third-party headers 和 C 库自己的 headers ——因为它们很少(如果有的话)在这种模式下进行测试。
它禁用污染用户命名空间的“system-specific predefined macros”(例如linux
、unix
、arm
)。这在抽象上是可取的,但与 #1 一样,有破坏库 headers 的严重倾向,很少(如果有的话)在这种模式下进行测试。
它 启用 trigraphs,这是使 C 与缺少一些标点符号的 ASCII 的“国家变体”一起工作的一个难题。它们很少被使用并导致如此多的实际混淆,以至于它们实际上被从 C++ 2017 中删除(不过不是 C 2017)。
要编译您自己的代码 具有相当挑剔的一致性诊断级别,但又不冒破坏库的风险headers,有更好的选项组合:
cc -std=gnuXX -g -Og -Wall -Wextra -Wpedantic -Wstrict-prototypes -Wwrite-strings
(选择一个合适的 XX;如果您没有理由选择其他任何东西,我会选择 11。)您可能想要也可能不想为 [=] 之一添加 -D
开关22=] feature selection macros;解释这些如何工作以及如何选择一个本身就是一个完整的问题。
这个问题不是如何删除警告
我正在写一个shell。我提到了这个 source。我在我的代码中使用了与他相同的 headers(顺序相同)。
编译他的代码时,我没有收到任何关于 getline
的 隐式声明 的警告。但是当我编译我的时,它确实被抛出。
手册页建议使用 #define _GNU_SOURCE
,并添加它从我的代码中删除了警告。
那么为什么博客中的代码没有抛出警告,因为他没有使用#define _GNU_SOURCE
?
这是最简单的代码(我复制了上面提到的所有 headers)
// #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);
| ^~~~~~~
您提到的教程的编写者似乎在测试代码时没有提供任何特殊的编译选项。我在那个页面的任何地方只看到一个编译命令,它是 gcc -o main main.c
。因此,他们获得了 GCC 的默认值,通常,这使得 getline
在拥有它的计算机上可用。
但是,您在编译代码时使用了编译器标志 -std=c11
。这个标志的作用之一是GCC指示C库的headers只声明ISO C2011规定的函数、常量、变量等。 (根据您使用的 C 库,此指令可能有也可能没有任何效果 — 但 Ubuntu 使用 GNU C 库,它彻底实现了它。)getline
不是 ISO C2011 的一部分,所以它没有被声明,当你尝试使用它时你会得到一个“隐式声明”诊断。
使用超一致性 -std=cXX
模式几乎总是错误的。 -std=cXX
和 -std=gnuXX
和 none 在实践中是可取的:
如上所述,它指示 headers 不要声明任何不属于 ISO C 指定修订版的内容。正如您亲眼所见,这几乎不是您想要的在编写一个重要的 C 程序时。它也有破坏库 headers 的严重倾向——包括 third-party headers 和 C 库自己的 headers ——因为它们很少(如果有的话)在这种模式下进行测试。
它禁用污染用户命名空间的“system-specific predefined macros”(例如
linux
、unix
、arm
)。这在抽象上是可取的,但与 #1 一样,有破坏库 headers 的严重倾向,很少(如果有的话)在这种模式下进行测试。它 启用 trigraphs,这是使 C 与缺少一些标点符号的 ASCII 的“国家变体”一起工作的一个难题。它们很少被使用并导致如此多的实际混淆,以至于它们实际上被从 C++ 2017 中删除(不过不是 C 2017)。
要编译您自己的代码 具有相当挑剔的一致性诊断级别,但又不冒破坏库的风险headers,有更好的选项组合:
cc -std=gnuXX -g -Og -Wall -Wextra -Wpedantic -Wstrict-prototypes -Wwrite-strings
(选择一个合适的 XX;如果您没有理由选择其他任何东西,我会选择 11。)您可能想要也可能不想为 [=] 之一添加 -D
开关22=] feature selection macros;解释这些如何工作以及如何选择一个本身就是一个完整的问题。