//File a.c
void main()
{
test();
}
//File b.c
#include<stdio.h>
void test()
{
printf("Hi, I am test.");
}
我使用「gcc a.c b.c」編譯此代碼。然後我運行'a.out',輸出結果是「你好,我正在測試」。我的問題是在a.c文件中沒有test()的聲明,爲什麼代碼要編譯?在沒有聲明的情況下在另一個文件中調用函數不會導致編譯錯誤
//File a.c
void main()
{
test();
}
//File b.c
#include<stdio.h>
void test()
{
printf("Hi, I am test.");
}
我使用「gcc a.c b.c」編譯此代碼。然後我運行'a.out',輸出結果是「你好,我正在測試」。我的問題是在a.c文件中沒有test()的聲明,爲什麼代碼要編譯?在沒有聲明的情況下在另一個文件中調用函數不會導致編譯錯誤
C語言中的函數是extern
默認情況下,這意味着連接將能夠給一個函數從文件a
連接到文件b
即使沒有程序員編寫#include
或extern
。
我的海灣合作委員會編譯它與這個警告:warning: implicit declaration of function...
的含義,通過看test();
編譯器猜測什麼test
是,並繼續。如果您已經定義test
爲static
會失敗,因爲static
櫃檯默認extern
一兩件事,我想你應該注意的是這implicit declaration
也使得編譯器猜測的test
返回類型,並且它會認爲類型是int
。這可能會導致問題。
代碼編譯,因爲這是C標準所要求的(至少在1999年之前)。支持在1999年標準中被刪除,儘管一些編譯器仍然支持它 - 儘管它們可以被配置爲在這種情況下發出警告(例如關於隱式聲明)。
具體而言,出於C89/90向預標準C的向後兼容性的考慮,代碼調用函數的嘗試隱式聲明該函數返回int
並接受可變參數列表。
這是當編譯器正在通過交流轉換器
鏈接時會發生什麼,它會工作,因爲函數具有相同的名稱。
如果調用函數的方式(返回值的用法和參數類型的數量)與函數的定義方式相匹配,這在實踐中可行。如果沒有匹配,結果可能是未定義的行爲。例如,如果函數是用4個參數定義的並且使用全部4個,但調用者提供了3個,則行爲是未定義的。同樣,如果函數被定義爲返回double
,但調用者認爲它返回int
。
實際上,最好在所有編譯單元被調用之前聲明所有函數(例如,通過包含一個頭文件)。這使得編譯器有機會檢查函數被調用的方式是否與其聲明匹配。
還要注意的是,在所有C標準中,main()
返回int
,而不是void
。支持main()
返回void
是一個編譯器擴展。
這些連接? –
您是否看到警告?當我在你的代碼中使用'gcc'時,我看到「隱式聲明'test'」的警告。 – lurker
購買C教程書。那麼你會明白爲什麼。切勿關閉警告 –