用下面的代碼:關於C函數原型和編修問題
int main(){
printf("%f\n",multiply(2));
return 0;
}
float multiply(float n){
return n * 2;
}
當我嘗試編譯,我得到一個警告:「‘%F’預計‘雙’,但參數的類型爲‘廉政’」和兩個錯誤:「相乘類型」,「以前的'乘法'隱式聲明在這裏。」
問題1:我猜測,這是因爲,由於編譯器沒有的功能「乘法」,當他遇到它的第一次,他將創造一個原型知識,併發明原型總是假定「詮釋」返回並作爲參數。所以本發明的原型將是「int multiply(int)」,因此也是錯誤。它是否正確?
現在,以前的代碼甚至不會編譯。但是,如果我在兩個文件中打破了這樣的代碼:
#file1.c
int main(){
printf("%f\n",multiply(2));
return 0;
}
#file2.c
float multiply(float n){
return n * 2;
}
,並執行「GCC在file1.c file2.c中-o文件」,它還是會給予一次警告(即printf的期待雙,但越來越INT )但錯誤不會再顯示出來並且會被編譯。
問題2:當我把代碼分解成2個文件時,怎麼會編譯它?
問題3:一旦我運行上面的程序(版本分成2個文件),結果是0.0000被打印在屏幕上。怎麼來的?我猜測編譯器再次發明了一個與函數不匹配的原型,但爲什麼打印0?如果我將printf(「%f」)更改爲printf(「%d」),它會打印出1.再次說明幕後發生的事情?
非常感謝。
有道理。唯一的一點仍不清楚,爲什麼編譯器不會找到與2個文件的謊言/矛盾。畢竟它仍然會在通過main.c運行時創建「int multiply(int)」原型,一旦它到達第二個文件,它將遇到「float multiply(float)」函數聲明,這明顯與先前的原型。 –
@DanielS好點!我編輯了答案,提到了爲什麼:本質上,編譯器一次編譯每個文件,每次編譯一個源文件。這不同於Java,它一次考慮所有文件。使用C和C++,每個翻譯單元(這是'.c'文件的花式名稱)被單獨編譯,然後鏈接器將結果彙總在一起。然而,當連接器進入遊戲時,所有的類型信息都消失了:連接器的字節,偏移量和地址水平低得多,因此它們也無法檢測到差異。 – dasblinkenlight
@DanielS:編譯器一次處理一個文件;在處理'file1.c'時,它對file2.c的內容一無所知,反之亦然。在構建'file1.c'時,它只知道'multiply'在使用前沒有被聲明。在構建'file2.c'時,它不知道'multiply'正在另一個翻譯單元中使用,沒有在範圍內進行正確的聲明。 –