Re: [問題] 關於printf的問題
※ 引述《zebraseven (Die walkuere)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Windows NT
: 問題(Question):
: 如果在一個程式裡
: 只打上一行printf("%d %d", 4*atan(1), sin(4*atan(1)));
: 我的執行結果會很奇怪,如下:
: 1413754136 1074340347
: 但是如果把第一個 %d 改成了 %g
: printf("%g %d", 4*atan(1), sin(4*atan(1)));
: 答案竟然變成了我想要的
: 3.14159 0
: 第一個答案怎樣我不管,
: 我的問題是第二個,它的輸出型態都是 %d
: 但為什麼第一次跟第二次的執行結果不一樣呢??
: 特別說一下,我沒有宣告任何的暫存變數,
: 程式碼就僅僅只有這兩行和標頭檔而已...
: 這問題實在讓在下百思不得其解...
: 有勞板上的大大們解惑!!
首先,要知道 4*atan(1) 這個結果是怎麼存在電腦記憶體裡面的
寫成二進位的話,它實際上是長這個樣子:
0100000000001001001000011111101101010100010001000010110100011000 約 3.14159
如果不知道為什麼,請找IEEE 754
0100000000001001001000011111101101010100010001000010110100011000
這一長串數字,如果從中間切成兩組32bit的數字:
01000000000010010010000111111011 = 1074340347
01010100010001000010110100011000 = 1413754136
有沒有覺得很眼熟?那就是你一開始印出來的東西了
printf("%d %d", 4*atan(1), sin(4*atan(1)));
這行的動作是這樣的:
(1) printf 第一次看到 %d, 它知道 %d 代表該印出 32 位元的整數
因此它從記憶體裡面拿出32元位長度的資料,並且印出來
這個時候拿到的是3.14159這個數字的後半段,1413754136
(2) printf 第二次看到 %d, 它知道 %d 代表該印出 32 位元的整數
因此它從記憶體裡面拿出32元位長度的資料,並且印出來
這個時候拿到的是3.14159這個數字的前半段,1074340347
(3) 兩個%d都印完了,任務結束,sin(4*atan(1))的結果被無視了
printf("%g %d", 4*atan(1), sin(4*atan(1)));
在我電腦上的執行結果是 3.14159 856972295,而不是你所說的 3.14159 0
改成這樣之後,就變成了
(1) printf 第一次看到 %g, 它知道 %g 代表該印出 64 位元的浮點數
因此它從記憶體裡面拿出64元位長度的資料,並且印出來
這個時候拿到的是完整的3.14159這個數字
(2) printf 第二次看到 %d, 它知道 %d 代表該印出 32 位元的整數
因此它從記憶體裡面拿出32元位長度的資料,並且印出來
這個時候拿到的是sin(4*atan(1))的後半的結果 856972295
(3) 兩個%g, %d都印完了,任務結束,sin(4*atan(1))另一半被無視
這就是為什麼您只是把第一個 %d 改成 %g
印出來的結果會導致第二個數不同
printf根據您所輸入的 %d 或 %g
決定從記憶體剩下的資料裡拿出多少出來印
至於為什麼在您的電腦上,可以跑出 0 這個數
這就是其他板友講的「未定義行為」了
根據不同的電腦、不同的printf實作
可能印出「856972295」或者「0」或者其他什麼莫名其妙的東西,都很正常
您可以把 sin(4*atan(1)) 換成別的東西,結果應該就不是那麼正確了
----
其實這篇文章是用結果去推斷過程的,畢竟我懶得挖printf原始碼XD
坦白說我不知道自己講的夠不夠正確,不過意思應該有點接近了
接下來就交給t大繼續補充 (傳棒子)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.35.184.77
※ 編輯: james732 來自: 114.35.184.77 (11/07 13:53)
推
11/07 14:07, , 1F
11/07 14:07, 1F
推
11/07 14:16, , 2F
11/07 14:16, 2F
推
11/07 14:19, , 3F
11/07 14:19, 3F
推
11/07 14:30, , 4F
11/07 14:30, 4F
推
11/07 14:30, , 5F
11/07 14:30, 5F
其實我已經省略了很多我自己都搞不懂的細節...XD
→
11/07 14:33, , 6F
11/07 14:33, 6F
→
11/07 14:33, , 7F
11/07 14:33, 7F
推
11/07 15:09, , 8F
11/07 15:09, 8F
如果是正妹的話,可以喔 (啥)
→
11/07 15:15, , 9F
11/07 15:15, 9F
→
11/07 15:16, , 10F
11/07 15:16, 10F
→
11/07 15:26, , 11F
11/07 15:26, 11F
→
11/07 15:30, , 12F
11/07 15:30, 12F
推
11/07 16:23, , 13F
11/07 16:23, 13F
→
11/07 16:51, , 14F
11/07 16:51, 14F
→
11/07 17:06, , 15F
11/07 17:06, 15F
→
11/07 17:20, , 16F
11/07 17:20, 16F
推
11/07 17:27, , 17F
11/07 17:27, 17F
→
11/07 18:40, , 18F
11/07 18:40, 18F
推
11/07 19:15, , 19F
11/07 19:15, 19F
→
11/07 19:15, , 20F
11/07 19:15, 20F
→
11/07 19:22, , 21F
11/07 19:22, 21F
→
11/07 19:36, , 22F
11/07 19:36, 22F
→
11/07 19:42, , 23F
11/07 19:42, 23F
.........
推
11/07 20:28, , 24F
11/07 20:28, 24F
→
11/07 20:28, , 25F
11/07 20:28, 25F
→
11/07 20:30, , 26F
11/07 20:30, 26F
→
11/07 20:31, , 27F
11/07 20:31, 27F
0xCCCCCCCC 這個東西寫VC就會覺得超親切的啊...XD
推
11/07 21:22, , 28F
11/07 21:22, 28F
→
11/07 21:22, , 29F
11/07 21:22, 29F
→
11/07 21:23, , 30F
11/07 21:23, 30F
→
11/07 21:34, , 31F
11/07 21:34, 31F
推
11/07 23:50, , 32F
11/07 23:50, 32F
→
11/07 23:51, , 33F
11/07 23:51, 33F
推
11/08 01:10, , 34F
11/08 01:10, 34F
→
11/08 01:13, , 35F
11/08 01:13, 35F
→
11/08 01:13, , 36F
11/08 01:13, 36F
→
11/08 01:13, , 37F
11/08 01:13, 37F
推
11/08 01:46, , 38F
11/08 01:46, 38F
推
11/08 02:11, , 39F
11/08 02:11, 39F
→
11/08 02:11, , 40F
11/08 02:11, 40F
→
11/08 02:12, , 41F
11/08 02:12, 41F
→
11/08 02:24, , 42F
11/08 02:24, 42F
→
11/08 11:09, , 43F
11/08 11:09, 43F
→
11/08 11:09, , 44F
11/08 11:09, 44F
→
11/08 11:09, , 45F
11/08 11:09, 45F
推
11/08 13:54, , 46F
11/08 13:54, 46F
→
11/08 13:55, , 47F
11/08 13:55, 47F
→
11/08 15:32, , 48F
11/08 15:32, 48F
→
11/08 15:33, , 49F
11/08 15:33, 49F
推
11/08 15:37, , 50F
11/08 15:37, 50F
→
11/08 15:47, , 51F
11/08 15:47, 51F
推
11/08 16:25, , 52F
11/08 16:25, 52F
真的長知識了,原來 0xCC 也是有典故的
※ 編輯: james732 來自: 140.117.171.40 (11/09 08:55)
→
11/09 09:04, , 53F
11/09 09:04, 53F
→
11/09 09:19, , 54F
11/09 09:19, 54F
推
11/09 09:49, , 55F
11/09 09:49, 55F
推
05/20 13:27, , 56F
05/20 13:27, 56F
討論串 (同標題文章)