printf
函數不知道您傳入的格式類型,因爲該部分是可變參數。
int printf(const char* format, ...);
// ^^^
在C標準,傳遞一個float
會自動提升爲double
(C11§6.5.2.2/ 6),而不是其他將在發送方完成。
在printf
裏面,因爲它不知道...
thingie(§6.7.6.3/ 9)的類型,所以它必須使用其他地方的提示 - 格式字符串。既然你已經通過了"%d"
,它正在告訴函數,預計有一個int
。
根據C標準,這導致了未定義的行爲(§7.21.6.1/ 8-9),其中包括打印一些奇怪的數字,故事結束的可能性。
但是究竟發生了什麼?在大多數平臺中,double
被表示爲「IEEE 754 binary64」格式,並且binary32格式表示float
。您所輸入的號碼將被轉換爲浮動,只有具有意義的23位,這意味着數字將這樣的近似:
3.3 ~ (0b1.10100110011001100110011) × 2¹ (actually: 3.2999999523162842...)
3.4 ~ (0b1.10110011001100110011010) × 2¹ (actually: 3.4000000953674316...)
3.5 = (0b1.11 ) × 2¹ (actually: 3.5)
3.6 ~ (0b1.11001100110011001100110) × 2¹ (actually: 3.5999999046325684...)
4 = (0b1 ) × 2² (actually: 4)
5 = (0b1.01 ) × 2² (actually: 5)
現在我們將它轉換爲加倍,它具有意義的53位,我們必須在這些數字的末尾插入30個二進制「0」,以產生例如
3.299999952316284 = 0b1.10100110011001100110011000000000000000000000000000000 ×2¹
這些主要是推導這些數字,它們是實際表示:
3.3 → 400A6666 60000000
3.4 → 400B3333 40000000
3.5 → 400C0000 00000000
3.6 → 400CCCCC C0000000
4 → 40100000 00000000
5 → 40140000 00000000
我建議使用http://www.binaryconvert.com/convert_double.html看不出這分解到±米×2 ë格式。
不管怎樣,我想你的系統是在正常設置在x86/x86_64的/ ARM,這意味着數字使用little-endian format在內存中擺出來,所以傳遞的參數會像
byte
#0 #1 ... #4 ... #8 ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 08 | 10 | 02 | 00 | | 00 | 00 | 00 | 60 | 66 | 66 | 0A | 40 | ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
address of "%d" content of 3.299999952316284
(just an example)
裏面的printf
,它消耗格式字符串"%d"
,解析它,然後找出該一個int
需要,因爲%d,所以4個字節從可變參數輸入拍攝,這是:
byte
#0 #1 ... #4 ... #8 ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
: 08 : 10 : 02 : 00 : | 00 | 00 | 00 | 60 | 66 : 66 : 0A : 40 : ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
address of "%d" ~~~~~~~~~~~~~~~~~~~
this, as an 'int'
所以,printf的將收到0x60000000,並將其顯示爲十六進制整數,即1610612736,這就是您看到該結果的原因。其他數字可以類似解釋。
3.3 → ... 60000000 = 1610612736
3.4 → ... 40000000 = 1073741824
3.5 → ... 00000000 = 0
3.6 → ... C0000000 = -1073741824 (note 2's complement)
4 → ... 00000000 = 0
5 → ... 00000000 = 0
+1需要時間寫出所有這些。 :) – Mysticial 2011-12-29 19:29:27
爲了完整起見,有兩個有用的補碼鏈接,[Two's Complement - Wikipedia](http://en.wikipedia.org/wiki/Two%27s_complement)和[Two's Complement notes Thomas Finley](http:// tfinley。淨/筆記/ cps104/twoscomp.html)。 – mctylr 2011-12-29 20:04:43