隐式声明警告:内置函数是什么?

时间:2013-11-14 19:09:27

标签: c gcc standard-library gcc-warning

问题界面正在标记许多“可能已经有你的答案的问题”,但我试图尽职尽责地检查是否有人问我到底在哪里。如果这是重复的话我很抱歉。

假设我有以下错误的程序:

extern void undefined_function(void);
int main(int argc, char **argv)
{
    undefined_function();
    undeclared_function();
    exit(0);
}

使用gcc编译:

$ gcc warnings.c 
warnings.c: In function ‘main’:
warnings.c:6:2: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
/tmp/ccVzjkvX.o: In function `main':
warnings.c:(.text+0x15): undefined reference to `undefined_function'
warnings.c:(.text+0x1f): undefined reference to `undeclared_function'
collect2: ld returned 1 exit status
$ 

我知道为什么会发出这些警告,以及如何纠正这些警告 - 这不是我的问题。

从输出中可以清楚地看出,gcc正在以不同的方式处理exit()与其他未定义/未声明的函数,因为它认为它是“内置函数”

对于给定的gcc,如何判断gcc认为是“内置函数”的函数列表是什么? 它是c标准库函数列表还是别的什么?

我考虑过做nm libc.so,但是在我的Ubuntu VM上,这个glibc似乎被剥离了,所以在这方面没有有用的信息:

$ nm /lib/x86_64-linux-gnu/libc.so.6
nm: /lib/x86_64-linux-gnu/libc.so.6: no symbols
$ 

3 个答案:

答案 0 :(得分:1)

列表很长,而且非常特定于平台。 C标准库中的许多(但并非全部)函数(有时)被视为内置函数。但是,还有一系列与特定处理器指令和其他硬件功能相关的内置函数。它们记录在here;特别链接的各个页面中,请参阅here, here, here, herehere.

答案 1 :(得分:0)

在深入了解gcc文档之后,我想我找到了一个合理的部分答案(though this answer is more complete in its references):

http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Other-Builtins.html#Other-Builtins

“GCC包含标准C库中许多功能的内置版本”(强调我的)。我认为这意味着大多数但并非所有标准库函数都是内置的。

文档继续介绍适用于c标准各个级别的几个列表:

“ISO C90函数abortabsacosasinatan2atan,{{1 },callocceilcoshcos,...“


不是gcc内置的标准库函数的示例是bsearch()。如果我在程序中添加对此的调用,没有exit并使用#include <stdlib.h>进行编译,我只会:

-Wimplicit-function-declaration

鉴于warnings.c:5:2: warning: implicit declaration of function ‘bsearch’ [-Wimplicit-function-declaration] ,我得到:

exit()

答案 2 :(得分:-1)

您正在编译允许隐式声明的C,因此隐式声明了您的“exit”。并且编译器信任您以后定义它。

如果暗示以通常的行为退出(隐含的原型与实际原型完全相同),那么隐式声明就可以了。它很好。

GCC只能告诉你内置内容,因为你知道对于C编译器,stdlib会在那里。这是它知道存在的唯一功能(内置),告诉你你暗示错误

否则我的桌面上可能会有一个定义原型的头文件,当在其他地方编译某些内容时会收到关于它的警告。 GCC必须在任何地方进行扫描,这是不可取的......所以,如果你隐式定义某些东西,稍后在翻译单元或实际版本(或另一个隐含的)不同意,你只会得到这样的隐含警告。

GCC知道stdlib =内置。

<强>附录

GCC接受你的说法,未定义的函数将存在,使用implict声明的东西,并没有任何矛盾,所以它没关系。它不知道undeclared_function应该是什么样子,但它知道exit应该是什么样的。

然后如你所知,链接器会抛出一个拟合(当然是正确的),因为它无法找到它们。