[英]Why C does not have a correct implementation of implicit conversion?
以下代碼打印99其中'c'被隱式轉換為99。
printf("%d", 'c');
但以下代碼打印0.000000:
printf("%f", 23);
為什么在第二種情況下整數23沒有像第一種情況那樣轉換成23.00000? 這是否反映了C中隱式轉換的執行不佳? 提前致謝。
編輯:如果沒有可能從int到float的提升作為答案之一,那么為什么我們寫時會有一個int浮動的提升
float x = 23;
為什么這樣?
在C中,'c' 是一個int
。 不執行轉換。
即使它是一個char
(因為它是在C ++), char
是整數類型,並且在像可變參數函數的參數列表printf
,所有可變參數經歷算術推廣,這會自動擴大一個char
到一個int
,或float
到一個double
- 但不是int
到double
。
printf
是一個可變參數函數,這意味着它的參數(除了第一個參數)在訪問它們時是有效的無類型。 這排除了printf
參數列表中的任何類型的智能類型轉換(盡管存在某些默認轉換 ,盲目地且不管格式說明符)。
在第一個例子中,'c'已經是一個int
。 但是在float的情況下,它沒有執行將int
轉換為float
所需的轉換,因為編譯器不知道它應該,或者更確切地說,根據規范,沒有什么可做但是相信格式說明符是關於類型的真實來源。 它認為數據已經是浮點數,因為格式說明符%f
告訴它,並且它無法看到傳入的23的類型。
這使得開發人員很容易意外地導致崩潰 - 開發人員必須確保格式說明符(例如%d)與自己提供的數據相匹配。 例如,將“%s”說明符與int
輸入混合會導致運行時崩潰,因為編譯器只是“相信”格式說明符沒有錯誤。 更糟糕的是,嘗試完全省略數據... printf("%f %f %f")
將導致它查找甚至不存在的參數,這些參數將崩潰。 遺憾的是編譯器必須接受並構建這個崩潰的代碼。
如果你想更仔細地看到這個難題,那就是printf
使用的google va_list
/ va_start
/ va_stop
。 了解這種機制允許我們遍歷發送到printf
的數據,但是,類型信息丟失了。 它是無類型的二進制數據,並且要使用它,它使用格式說明符%f
來實現浮點數就在那里。 然后它將二進制數據解釋為float
並在顯示之前將其寫入字符串。
換個角度來看待它是編譯器忽略像字符串內容%f
在其類型的系統...... %f
被編譯但它僅在運行時同時運行功能應用。 但是在運行時,所有類型信息都會丟失--C有一個類型系統,但它只是編譯時間。 基本上,像%f
和C類型系統這樣的字符串數據是完全沒有通信的外來概念。 所以試着想象你的程序沒有像%f
那樣的字符串數據。 編譯器如何知道運行編譯時int-> float轉換?
同樣,這僅適用於可變函數,而不適用於常規函數調用。 普通函數調用表現出類似於大多數現代語言的類型處理。 另一方面,Variadic函數對於C來說是唯一的。與void *
指針類似,它們應該被認為是危險的並且小心使用。
編輯: float x = 23;
因為語言具有功能類型系統而導致促銷(盡管類型僅在編譯時已知)。 類型系統在variadic函數參數內部不起作用,即printf
的輸入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.