從sprintf函式談符號擴充套件問題

2021-09-06 06:55:44 字數 1844 閱讀 1251

這裡要注意乙個符號擴充套件的問題:比如,假如我們想列印短整數(

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,可...