问题描述
我有简单的应用程式:
I have simple application:
#include <stdio.h>
int main( int argc, char ** argv )
{
printf( "hello");
exit( 0 );
}
当我使用命令编译它时
When I compile it with command
gcc -c count_words.c
I有警告:
I have warning:
warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
exit( 0 );
我试图找到 exit()
功能被定义。并发现它在 stdlib.h
中定义。但它不包含在我的项目中,并且在编译命令中没有定义其他库。
I was trying to find where exit()
function is defined. And found that it is defined in stdlib.h
. But it is not included in my project and no additional libs defined in compile command.
如果我错了,纠正我,但看起来像 gcc
将一些库作为默认值。什么是这些库,是否有可能告诉gcc不包括它们?
Correct me if I'm wrong, but looks like gcc
takes some libs as default. What are these libs and is it possible to tell gcc not include them?
为什么编译器不满意 exit(0)
假设它以某种方式包含 stdlib.h
作为默认值?
Why compiler is not happy regarding exit(0)
assuming that it somehow includes stdlib.h
as default?
推荐答案
Let's take your example:
#include <stdio.h>
int main( int argc, char ** argv )
{
printf("hello\n");
exit(56);
}
虽然我们在汇编时收到警告:
Although we get a warning on compilation:
~$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
exit(56);
^
test.c:6:5: warning: incompatible implicit declaration of built-in function ‘exit’
test.c:6:5: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
无论如何,我想你已经尝试过运行它并确保它可以正常工作:
Anyway, I think you have tried to run it and make sure it works:
~$ ./test
hello
~$ echo $?
56
是正确的,当他说:
@Mat was right when he said that:
C
编译器和链接器是完全单独的工具。让我们看看这个。实际上,这个程序依赖于标准的C库(如果你没有将 -nostdlib
传递给编译器)以及一些系统库(如loader和vdso) 。您可能会看到它:
The C
compiler and linker are totally separate tools. Let's look on this. Actually, this program depends on the standard C library (as all programs if you didn't pass -nostdlib
to compiler) and a couple of system libraries (like loader and vdso). You may see it with:
~$ ldd test
linux-vdso.so.1 (0x00007fff1b128000)
libc.so.6 => /lib64/libc.so.6 (0x00007f804389f000)
/lib64/ld-linux-x86-64.so.2 (0x0000557744537000)
这三个库是任何程序的最小集合。在我们的例子中, exit
函数是在标准库中定义的,或者是 libc.so.6
。现在我们来看看详细模式下的编译过程。您可以通过将 -v
或 - verbose
选项传递给编译器来实现此目的:
These three library is a minimal set for any program. The exit
function is defined in the standard library or libc.so.6
in our case. Now let's look on the compilation process in verbose mode. You can achieve this by the passing -v
or --verbose
option to compiler:
gcc test.c -o test --verbose
如果您执行此操作,您会发现如下所示的行:
If you will execute this, you will find lines like these:
#include <...> search starts here:
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include
/usr/local/include
/usr/include
因此,compile知道在哪里搜索 stdlib
的头文件,搜索它以查找非本地功能的声明。请注意,它仅在您的源代码文件中包含的头文件中进行搜索。它可以在 stdio.h
中找到 printf
声明,但找不到退出。
So, compile knows where to search header files for stdlib
and it starts to search it to find declaration for non-local functions. Note that it searches only in header files which are included in your source code file. It can find printf
declaration in thestdio.h
, but can't locate declaration of the exit
.
在此步骤之后,编译开始将程序与库链接起来:
After this step, the compile starts to link your program with libraries:
/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2 ... -lc ...
其中 collect2
是gcc util,它试图将您的程序与 lc
这是标准的C库。请注意,该过程由两个步骤组成:编译和链接。这就是为什么你的程序能正常工作。
Where collect2
is gcc util which tries to link your program with lc
which is standard C library. Note that the process consists from two steps: compilation and linking. That's why your program works.
另外, gcc
支持 -M
选项,它会告诉你主文件的依赖关系。所以,如果你要执行它,你会看到一组头文件,包括 stdio.h
,但不是 stdlib.h
:
Additionally, gcc
supports -M
option which will tell you about dependencies of the main file. So, if you will execute it, you will see the set of header files including stdio.h
, but not stdlib.h
:
$ gcc -M test.c
test.o: test.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
/usr/include/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
甚至尝试将 -E
选项传递给 gcc
:
Or even better, try to pass -E
option to gcc
:
$ gcc -E test.c
第一次看到结果舞台 - 预处理阶段。我认为这是理解你为什么得到这个警告的最简单的方法。
and you will see result right after the first stage - preprocessing stage. I think it is the easiest way to understand why you are getting this warning.
这篇关于使用GCC编译C项目时采用哪些默认库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!