預期的行爲是您的函數將被調用,只要目標文件鏈接在一起。任何未聲明的函數都被假定爲一個外部函數,該函數返回一個用於編譯目的的整數,以及一個用於鏈接目的的外部符號(指向對象文件)。我給你具體的例子:
foo.c的:
void foo(const char *name) {
printf("foo called with %s\n", name);
}
bar.c:
void bar(int a) {
printf("bar called with %d\n", a);
}
的main.c:
int main(int argc, char *argv[]) {
foo("Hello");
bar(5);
return 0;
}
使用編譯的目標文件gcc:
gcc -fno-builtin -ansi -c -o foo.o foo.c
gcc -fno-builtin -ansi -c -o bar.o bar.c
gcc -fno-builtin -ansi -c -o main.o main.c
這些不應產生任何警告或錯誤
現在它們關聯起來:
gcc -o progy main.o bar.o foo.o
請注意,我用gcc的二進制文件鏈接,但那是等價的:
ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o progy /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbegin.o main.o foo.o bar.o -lc -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1 -lgcc -lgcc_s /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtend.o /usr/lib64/crtn.o
在我的Linux 64位平臺上。不管是什麼您的構建目標平臺(GCC實際運行LD這樣做鏈接)
使用您的C編譯器(在我的情況,GCC)的鏈接將確保連接器調用正確。如果你使用IDE,那麼這些步驟都被一個漂亮的界面所隱藏。
原型和頭文件夾雜宣言無關與生成的二進制文件的鏈接階段。任何C編譯器都會在最簡單的情況下拋出一個警告。在那裏你會得到一個警告的時間,比如使用gcc是,如果你有丟失的原型上的警告標誌,甚至然後它只是提高了全局函數和只爲實現該功能,並沒有正式存在的原型源文件。 ANSI C專門允許在沒有原型的情況下調用函數。 –
@Ahmed我同意你的看法,它的沒有直接關係,但我的觀點是,通過不提供原型編譯器刪除檢查的一個水平。如果你與原型不匹配,編譯器會給你一個錯誤。如果你沒有原型,那麼它會落在鏈接器上來捕捉錯誤。你*希望*編譯器來捕捉錯誤,所以給它一個原型,以便它可以完成它的工作。 – bearda