作者xatier (新生)
看板C_and_CPP
標題[問題] printf("%x%x", 0.1);
時間Thu Nov 10 22:56:30 2011
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Linux / FreeBSD
(64bit) (32bit)
問題(Question):
剛剛上計概課時,老師提到了浮點數的內部二進位表達方式
並舉了下面這個例子
http://i.imgur.com/2zL8T.png
我當下非常好奇用 %x%x 印出 0.1 的結果
直接用筆電寫出下面的測試程式
// gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
#include <stdio.h>
int main(){
printf("%x%x\n", 0.1);
return 0;
}
gcc vet.c
印出了奇怪的結果
./a.out
300eab68300eab78
超神奇的
多完個幾次之後發現見鬼了
怎麼每次 compile 出來都不一樣 = =
http://i.imgur.com/SkUlc.png
我去問教授,教授思考了很久
表示:『compiler 的問題,你回去用 VC++ 試試』
=========================
我回寢室後用我工作站的機器寫了一樣的 code
// gcc version 4.2.1 20070719 [FreeBSD]
10:43pm xatier@sa [~] [W2] >vim foo.c
10:43pm xatier@sa [~] [W2] >gcc foo.c
10:43pm xatier@sa [~] [W2] >./a.out
9999999a3fb99999
10:43pm xatier@sa [~] [W2] >gcc foo.c
10:43pm xatier@sa [~] [W2] >./a.out
9999999a3fb99999
10:43pm xatier@sa [~] [W2] >gcc foo.c
10:43pm xatier@sa [~] [W2] >./a.out
9999999a3fb99999
沒噴警告也沒發生問題阿?
求觀念導正 Orz
補充說明(Supplement):
另外想知道 printf() 內部到底是怎麼做的?
老師說 printf() 會把後面全部的 args 吃進去放到某個空間
然後依照你給的 formatted string 按照每一種 data type 去切割資料
假如是 int 就挖出 4 byte 出來這樣
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.113.24.36
→ x000032001:以樓主的強大程度看一下asm的function call應該就懂了 11/10 22:59
推 tropical72:我昨天剛好在試這個試半天試不出來,最後方法在 11/10 23:02
→ tropical72:#1Ekuf5w4, 最後一次修改那段。 11/10 23:03
→ tropical72:然後再補一下,你們老師的說法,必需基於 big endian 11/10 23:09
→ tropical72:才會成立,little 的話 hi/low 4bytes 會相反。 11/10 23:10
→ xatier:我知道big/little 會有相反的結果,可是我不懂 asm... 11/10 23:12
→ xatier:有人可以幫我解釋一下嗎 11/10 23:12
看不懂 asm 於是我又做了另一個實驗
把他改成下列這樣
printf("%x %x %x %x %x %x %x %x\n", 0.1);
bf260d88 bf260d98
400520 4005b0 e7858f10 0 e74cc30d 0
ba937a98 ba937aa8
400520 4005b0 6a066f10 0 69cda30d 0
2fe07f58 2fe07f68
400520 4005b0 b8727f10 0 b839b30d 0
320babe8 320babf8
400520 4005b0 632d3f10 0 62f4730d 0
中間這幾位神奇的一樣了 \("▔□▔)/
※ 編輯: xatier 來自: 140.113.24.36 (11/10 23:21)
→ legnaleurc:va_list pop 出來的個數就不對啊 ... 11/10 23:21
→ tropical72:... 不要做無謂的嚐試.. 11/10 23:22
→ tropical72:奇怪,gcc下,你的方法正常啊!! 我給的show3不正常就是了 11/10 23:27
→ akasan:因為浮點數的參數跟整數放參數的方法不一樣阿 11/11 00:11
→ akasan:printf("%x%x\n", 0.1); vs printf("%x%x\n", 1, 0.1); 11/11 00:13
→ akasan:兩個去gcc -S 看組合語言就知道怎麼一回事了 11/11 00:13
→ akasan:跟 ABI 有關 11/11 00:13