printf() 函式進階格式轉換說明
二進位轉為字元格式
printf()
函式最主要的功能是將各種型態的變數內之資料以字元的格式顯示在螢幕上,
例如:
int ix=76;
float fx=1.25e8;
char cx = 'C';
printf("ix=%d %x, fx=%f cx=%c %d %x",ix,ix,fx,cx,cx,cx);
其列印結果如下:
ix=76 4c, fx=125000000.000000 cx=C 67 43
除了將字元變數以字元格式顯示到螢幕上時,
完全不需要做任何轉換,
其他的列印工作都需要做格式的轉換,
例如:
int ix=81;
printf("%d",ix);
並不因為以十進位整數形式列印整數變數就不用格式轉換,
用 2 進位的格式來看這十位數整數變數的內容應該是
0000 0000 0101 0001,
如此的數字如何轉換為螢幕上的輸出字元 '8' 與 '1' 呢?
('8' 與 '1'這兩個字元的 ASCII 碼是 0x38 及 0x31)
其實很簡單:
-
步驟一:
81 = 8*10 + 1 (除以 10 得到商數 8,餘數 1)
這個餘數 1 必須轉為 ASCII 的字元 '1',
可以利用下面程式片段來轉換
int remainder;
char c;
remainder = ix % 10;
c = remainder + '0';
putchar(c);
-
步驟二:
步驟一的商 8 = 0*10 + 8 (除以 10 得到商數 0,餘數 8)
這個 8 必須轉為 ASCII 的 '8',
可以利用下面程式片段來轉換
quotient = ix / 10;
remainder = quotient % 10;
c = remainder + '0';
putchar(c);
當然這只是一個示範性的程式,
你要設計的話要加上迴圈的控制,
如此程式才能處理任意位數的轉換工作。
有興趣的話,請你寫寫看這個列印整數的程式,
你也可以嘗試寫一個用十六進位列印整數的程式
printf() 的參數如何工作
printf() 函式在 stdio.h 內的宣告如下:
int _cdecl printf(const char *__format, ...);
意思是 printf() 函式會將第一個字元陣列參數當作格式字串來使用,
例如:
"%d %ld %x %lx %f %lf %c %u %lu"
其後的 ... 則表示 C 編譯器不去檢查傳入的參數個數及型態,
以 TURBO C 16 位元的 Compiler 在 Small 模式下為例,
在這種情況下參數傳入函式時只有三種大小並且順序排列,
端視傳入參數本身的型態而定:
-
二個位元組:(unsigned) char, short, int, 常數 5, 字元常數 'c'
-
四個位元組:(unsigned) long, 常數 5L
-
八個位元組:float, double, 常數 1.0
參考下例:
char x = 'c';
int y = 0x9999;
long z = 0xaabbccdd;
float f = 1.0;
int a = 0xffff;
printf("%c %d %ld %f %lx", x, y, z, f, a);
其參數排列之情形如下表:
x
|
y
|
z
|
f
|
a
|
63
|
00
|
99
|
99
|
dd
|
cc
|
bb
|
aa
|
00
|
00
|
00
|
00
|
00
|
00
|
f0
|
3f
|
ff
|
ff
|
printf() 函式則依照格式字串中的各種格式以下列規則
由傳入的參數位元陣列中依序轉換各個參數:
- %c: 2 bytes
- %d: 2 bytes
- %ld: 4 bytes
- %x: 2 bytes
- %lx: 4 bytes
- %u: 2 bytes
- %lu: 4 bytes
- %f (%lf): 8 bytes
注意:在 32 位元的 C 編譯器上 ld 與 d 相同,
lx 與 x 相同,
萬一程式設計者沒有將兩者對齊的話就一定會出錯,例如:
- printf("%x", 0xaabbccddL); 得到 ccdd
- printf("%x %x",0xaabbccddL,0x01); 得到 ccdd aabb