我正在閱讀 K&R C 書,第 4.2 章內容如下:
如果 atof 本身和 main 中對它的呼叫在同一個源檔案中的型別不一致,編譯器會檢測到錯誤。但是,如果(更有可能)單獨編譯 atof,則不會檢測到不匹配,atof 將回傳一個 double,main 將其視為 int,并且會產生無意義的答案。
我想親眼看看如果我創建并不一致地使用他們描述的函式會發生什么:
主檔案:
#include <stdio.h>
int floatFunction();
int main() {
int result = floatFunction();
printf("result: %d\n", result);
}
floatFunction.c:
float floatFunction() {
return 10;
}
重擊:
$ gcc main.c floatFunction.c -o main
$ ./main
result: 0
$
不管我有什么floatFunction回報,我總是得到0結果。我也嘗試編譯-o3,結果相同。結果我期待看到10.0解釋為 int的位模式。為什么這不會發生?
另外,為什么編譯程序沒有通知我型別不匹配以及我如何保護自己在實際代碼中不犯這樣的錯誤?
uj5u.com熱心網友回復:
至少在 x86 上有不同的暫存器用于傳遞(和回傳)浮點與整數值(指標和整數)。
為什么在整數值的回傳暫存器中始終使用整數零,而浮點值的回傳暫存器用于真正的回傳值,我不知道。可能只是運氣。
有關 Linux 呼叫約定的更多資訊,請參見例如i386 和 x86-64 上的 UNIX 和 Linux 系統呼叫(和用戶空間函式)的呼叫約定是什么。
無論如何,請記住,無論您觀察到什么,至少在語言層面,它都只是未定義的行為,任何事情都會發生。
uj5u.com熱心網友回復:
我期待看到 10.0 的位模式因此被解釋為 int。為什么這不會發生?
最可能的原因是在您的平臺上(您沒有指定)浮點值在與回傳整數值的暫存器不同的暫存器中回傳。
例如,在暫存器中x86_64回傳整數結果rax,而在暫存器中回傳雙精度和浮點數結果xmm0。
這是一篇關于各種x86呼叫約定的文章。
如果您不在 上x86_64,則需要查找適用于您平臺的呼叫約定。
另外,為什么編譯程序不通知我型別不匹配
編譯程序一次只能看到一個源檔案(編譯單元),所以它不能警告你。
聯結器可以,但實際上只有 AIX 聯結器可以(我知道的那些)。
我怎樣才能保護自己在實際代碼中不犯這樣的錯誤?
通過在頭檔案中宣告您的函式并在兩個編譯單元中包含該頭檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/393253.html
上一篇:在C中調整視窗小故障
