考慮snippet 1:
#include <stdio.h>
int main() {
float val;
val = fun(2, 4);
printf("%f", val);
return 0;
}
float fun(int x, int y){
return x y;
}
代碼snippet 2:
#include <stdio.h>
int main() {
int val;
val = fun(2, 4);
printf("%d", val);
return 0;
}
int fun(int x, int y){
return x y;
}
如果是片段 1,它會給我錯誤,如下所示:
gcc /tmp/1cUl25Ux4O.c -lm
/tmp/1cUl25Ux4O.c: In function 'main':
/tmp/1cUl25Ux4O.c:6:11: warning: implicit declaration of function 'fun' [-Wimplicit-function-declaration]
6 | val = fun(2, 4);
| ^~~
/tmp/1cUl25Ux4O.c: At top level:
/tmp/1cUl25Ux4O.c:11:7: error: conflicting types for 'fun'
11 | float fun(int x, int y){
| ^~~
/tmp/1cUl25Ux4O.c:6:11: note: previous implicit declaration of 'fun' was here
6 | val = fun(2, 4);
| ^~~
但在第二個片段的情況下,我得到了正確的輸出。(即6)。
在這兩種情況下,我都省略了函式宣告,只存在定義部分,并且在 main() 之后也是如此。但是,如果 incase snippet 1,如果我更改順序并在 main() 之前定義 fun(int, int),我將獲得所需的輸出。(即6.0000)
我無法弄清楚。
為什么會這樣?
是因為函式被推入堆疊的順序嗎?
如果這是原因,那么為什么代碼片段 2 中的代碼有效?
請向我提供參考/解釋。謝謝!
Update:
In the error log for snippet 1, it says that there are conflicting types for fun. But there's just one fun(int, int) present in the code. What is creating conflict?
uj5u.com熱心網友回復:
第一個片段:
int main() {
float val;
val = fun(2, 4);
printf("%f", val);
return 0;
}
float fun(int x, int y){
return x y;
}
val = fun(2, 4);你在編譯的時候寫main的還沒有遇到float fun(int x, int y)。因此它假設它fun是這樣宣告的:(int fun();函式回傳一個int并采用任意數量的任何型別的引數。
然后編譯器遇到float fun(int x, int y),但如前一段所述,編譯器現在假設fun回傳 an int,因此發生沖突。
如果你放float fun(int x, int y) before main,編譯器會遇到float fun(int x, int y)并且現在知道它fun回傳 afloat并且正好接受兩個int引數。
隱式宣告已成為過去,現在不應該使用它們。
順便提一句:
這里不涉及未定義的行為。未定義的行為是完全不同的。
我建議您閱讀以下內容:未定義、未指定和實作定義的行為
uj5u.com熱心網友回復:
但在第二個片段的情況下,我得到了正確的輸出。
不,它也不編譯。因此,讓您擺脫編譯器已經發現錯誤的故障排除代碼的頭痛,確保使用符合標準的 C 編譯器,請參閱哪些編譯器選項推薦給初學者學習 C?
當使用正確配置的 C 編譯器時,我們得到這個錯誤:
錯誤:函式'fun'的隱式宣告
一些編譯器決定在未設定為嚴格遵從模式時生成可執行檔案的原因是歷史性的。32 歲(古老!)編譯器有一個稱為“隱式函式宣告”和“隱式 int”的功能。這意味著當編譯器遇到對尚未宣告/定義的函式的函式呼叫時,它會猜測該函式的回傳型別為int. 因為為什么不 - 在某些情況下它可能是正確的型別!
如果不是,我們會得到未定義的行為,任何事情都可能發生。例如函式回傳 afloat但呼叫者將其原始二進制表示float視為int. 或者程式崩潰。
在 23 年前(!)之前發布的 C99 版本中,該語言設計缺陷已從 C 中洗掉。
您可能沒有理由使用古老的編譯器模式,因此只需使用上面鏈接中給出的選項進行編譯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/448216.html
上一篇:在C中,如何在呼叫vsnprintf()之前將可變數量的引數(比如50 )傳遞給va_start()理解的函式?
