作者LPH66 (f0VMRgEBA)
看板C_and_CPP
標題Re: [問題] printf 顯示問題
時間Wed Jul 17 19:53:16 2013
※ 引述《twayfind (橘水壎)》之銘言:
: #include <stdio.h>
: int main(void)
: {
: int a=10;
: int b=20;
:
: float d=0;
:
: d=(float)a/b;
:
: printf("%d,%.3f\n",d,d);
: printf("%.3f,%d\n",d,d);
: return 0;
: }
: → kiedveian:先轉型成整數 07/17 15:07
: 推 lc85301:我比較好奇為什麼前一個參數的轉換影響到下一個整數? 07/17 17:01
printf (及 scanf) 是使用 C 語言的可變參數下去實作
這種可變參數有幾個限制
首先函式不會知道你傳了什麼東西進去 得要有另外的方法來指名才行
printf/scanf 的做法是傳入一個格式字串以表示後面有哪些參數
再來 不到 int 等級的整數會升級成 int 再傳 float 則會升級成 double
因此這裡推入了兩個 float 實際上傳進 printf 裡時是兩個 double
(所以其實 printf 裡指定 %f 跟 %lf 是一樣的)
而 %d 這個格式會去抓一個 int 出來
但是在 32-bit 的架構下 int 跟 double 是不一樣大的
(int 佔 4 byte double 佔 8 byte)
所以在 %d,%.3f 的狀況下 printf 會這樣去抓值:
┌ 第一個 d ┐ ┌ 第二個 d ┐
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
└ %d ┘ └ %.3f ┘
自然就會跟 %.3f,%d 時抓到的不一樣了:
┌ 第一個 d ┐ ┌ 第二個 d ┐
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
└ %.3f ┘ └ %d ┘
無論如何 %d 抓到的一定是錯誤的值 所以一定會有怪結果
在那之後的結果也就不一定正確了
--
題外話:
%f 跟 %lf 在 scanf 裡則有差
因為這時傳進 scanf 的參數全是指標
而 float * 跟 double * 這是兩種指標
所以必須要分開這兩者才行
--
LPH [acronym]
= Let Program Heal us
-- New Uncyclopedian Dictionary, Minmei Publishing Co.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 122.118.141.187
※ 編輯: LPH66 來自: 122.118.141.187 (07/17 19:55)
→ purincess:你啥時回到人間啊是說 07/17 19:59
→ purincess:再半年? 07/17 19:59
→ purincess:噢 忘了先跟lph擊掌 (拍擊lph (?)) 07/17 19:59
推 cuteclare:/膜拜 07/17 20:29
推 twayfind:感謝大大的解說 07/17 20:53
→ hilorrk:從錯誤的使用方法和結果中也可以學習~ 07/17 22:23
推 azureblaze:我一直以為varg是array of void*,原來是直接疊起來 07/17 22:27
→ MOONRAKER:我也以為是這樣 07/17 22:35
→ purincess:所以用stdcall做printf然後參數給的比%數少的話該不會會 07/17 22:38
→ purincess:爆炸... 07/17 22:38
→ LPH66:stdcall 是 callee 清堆疊所以不能用可變參數... 07/17 23:13
→ purincess:可是c standard應該是沒有規定這個吧 @@ 07/17 23:24
推 a60301:<(_ _)> 07/18 04:00
推 lc85301:worship 07/18 05:30