這裡要注意乙個符號擴充套件的問題:比如,假如我們想列印短整數(
short
)-1
的記憶體16
進製表示形式,在
win32
平台上,乙個
short
型佔2
個位元組,所以我們自然希望用4 個
16 進製數字來列印它:
short si = -1;
sprintf(s, "%04x", si);
產生「ffffffff
」,怎麼回事?因為
spritnf
是個變參函式,除了前面兩個引數之外,後面的引數都不是型別安全的,函式更沒有辦法僅僅通過乙個「
%x」就能得知當初函式呼叫前引數壓棧時被壓進來的到底是個
4 位元組的整數還是個
2 位元組的短整數,所以採取了統一
4 位元組的處理方式,導致引數壓棧時做了符號擴充套件,擴充套件成了
32 位的整數
-1,列印時
4 個位置不夠了,就把
32 位整數
-1 的8 位
16 進製都列印出來了。
如果你想看
si 的本來面目,那麼就應該讓編譯器做
0 擴充套件而不是符號擴充套件(擴充套件時二進位制左邊補
0 而不是補符號位):
sprintf(s, "%04x", (unsigned short)si);
就可以了。或者:
unsigned short si = -1;
sprintf(s, "%04x", si);
sprintf 和
printf
還可以按
8 進製列印整數字串,使用」
%o」。注意
8 進製和
16 進製都不會列印出負數,都是無符號的,實際上也就是變數的內部編碼的直接的
16 進製或
8 進製表示。
控制浮點數列印格式
浮點數的列印和格式控制是
sprintf
的又一大常用功能,浮點數使用格式符
"%f"
控制,預設保留小數點後
6 位數字,比如:
sprintf(s, "%f", 3.1415926); //產生
"3.141593"
但有時我們希望自己控制列印的寬度和小數字數,這時就應該使用:」
%m.nf
」格式,其中
m 表示列印的寬度,
n 表示小數點後的位數。比如:
sprintf(s, "%10.3f", 3.1415626); //產生:
" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產生:
"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產生:
"3.142"
注意乙個問題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會打出什麼東東來?「
100.00
」?對嗎?自己試試就知道了,同時也試試下面這個:
sprintf(s, "%.2f", (double)i);
第乙個打出來的肯定不是正確結果,原因跟前面提到的一樣,引數壓棧時呼叫者並不知道跟
i相對應的格式控制符是個」
%f」。而函式執行時函式本身則並不知道當年被壓入棧裡的是個整數,於是可憐的儲存整數
i 的那
4 個位元組就被不由分說地強行作為浮點數格式來解釋了,整個亂套了。不過,如果有人有興趣使用手工編碼乙個浮點數,那麼倒可以使用這種方法來檢驗一下你手工編排的結果是否正確。
原文:
從Hint 談遊戲中擴充套件文字控制項
題目有點大,但實際上是很簡單的事情,也許一兩句話就說完了。組成文字控制項的核心物件 unit 最小顯示單元的抽象。line 用於組織顯示的物件,主要用於可見部分的文字和內容的構造,記錄了一組unit所在的位置。chunk 文字控制項內部儲存unit的容器,不記錄unit的位置資訊,乙個文字控制項裡應...
從printf談可變引數函式的實現
從printf談可變引數函式的實現 摘要 一直以來都覺得printf似乎是c語言庫中功能最強大的函式之一,不僅因為它能格式化輸出,更在於它的引數個數沒有限制,要幾個就給幾個,來者不拒。printf這種對引數個數和引數型別的強大適應性,讓人產生了對它進行探索的濃厚興趣。關鍵字 printf,可變引數 ...
從printf談可變引數函式的實現
從printf談可變引數函式的實現 戎亞新 摘要 一直以來都覺得printf似乎是c語言庫中功能最強大的函式之一,不僅因為它能格式化輸出,更在於它的引數個數沒有限制,要幾個就給幾個,來者不拒。printf這種對引數個數和引數型別的強大適應性,讓人產生了對它進行探索的濃厚興趣。關鍵字 printf,可...