讓我們把你的例子:
#include <stdio.h>
int main(int argc, char ** argv)
{
printf("hello\n");
exit(56);
}
雖然我們得到編譯警告:
~$ 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’
無論如何,我認爲你已經嘗試運行它,並確保它的工作原理:
~$ ./test
hello
~$ echo $?
56
@Mat他說得對:
你在混淆包括標題和鏈接到庫。這些都是 兩個完全不同的事情
的C
編譯器和鏈接都完全單獨的工具。讓我們看看這個。實際上,這個程序依賴於標準的C庫(因爲所有的程序如果你沒有通過編譯器-nostdlib
)和一些系統庫(如loader和vdso)。你可能會看到它:
~$ 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
選項實現這個編譯器:
gcc test.c -o test --verbose
如果您將執行此,你會發現這樣的詩句:
#include <...> search starts here:
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include
/usr/local/include
/usr/include
所以,編譯知道到哪裏尋找頭文件對於stdlib
,它開始搜索它以查找非本地函數的聲明。請注意,它僅在您的源代碼文件中包含的頭文件中進行搜索。它可以在stdio.h
中找到printf
聲明,但找不到exit
的聲明。
此步驟後,編譯開始你的程序與庫鏈接:
/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2 ... -lc ...
哪裏collect2
是試圖程序與lc
鏈接這是標準C庫GCC UTIL。請注意,該過程由兩個步驟組成:編譯和鏈接。這就是你的程序工作的原因。
此外,gcc
支持-M
選項,它會告訴你主文件的依賴關係。所以,如果你將執行它,你會看到一組的頭文件,包括stdio.h
,但不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
:
$ gcc -E test.c
和您會在第一階段 - 預處理階段後看到結果。我認爲這是理解你爲什麼得到這個警告的最簡單的方法。
相關:http://stackoverflow.com/q/8930641/3049655 –
你在混淆包括標題和鏈接到庫。這是兩個完全不同的東西。 – Mat
那麼,在哪個庫退出(int)存在?而我的編譯命令不包含任何庫。 – vico