格式字串完整語法
%[旗標][寬度][.精度][長度]類型
旗標
| 旗標 | 效果 | 範例 |
- | 左對齊 | %-10s |
+ | 正負號皆顯示 | %+d → +42 |
空格 | 正數前加空格,負數加 - | % d → 42 |
# | 替代形式 | %#x→0x2a, %#o→052, %#f強制小數點 |
0 | 前導零填寬(數值型) | %05d → 00042 |
寬度與精度
m:最小欄寬,不足補空格(或 0)
.n:精度
- 整數:最小位數,前導零補足
- 浮點:小數點後位數
- 字串:最大字元數(截斷)
*:由引數動態指定 printf("%*.*s", w, p, str)
長度修飾
| 修飾 | 對應類型 | 備註 |
hh | signed char, unsigned char | C99 |
h | short, unsigned short |
l | long, unsigned long, double (f) | %lf 等同 %f |
ll | long long, unsigned long long | C99 |
j | intmax_t, uintmax_t | C99 |
z | size_t, ssize_t | C99 |
t | ptrdiff_t | C99 |
L | long double |
類型轉換字元完整表
| 字元 | 輸出 | 範例 |
d, i | 有號十進位整數 | 42, -7 |
u | 無號十進位整數 | 42 |
o | 八進位 | 52 |
x, X | 十六進位 (小寫/大寫) | 2a, 2A |
f, F | 定點小數 | 3.141593 |
e, E | 科學記號 | 3.141593e+00 |
g, G | 自動選 f/e 較短者 | 3.14159 |
a, A | 十六進位浮點 (C99) | 0x1.921fbp+1 |
c | 單一字元 | A |
s | 字串 | hello |
p | 指標位址 | 0x7ffc1234 |
n | 已輸出字元數寫入指標 | 安全風險,建議禁用 |
% | 字面 % | %% → % |
進階技巧與陷阱
動態寬度/精度
printf("%*.*f\n", width, prec, val); // 寬度、精度由變數控制
輸出字元計數 %n(危險)
int cnt;
printf("Hello%n World", &cnt); // cnt = 5
格式化字串攻擊向量,現代編譯器 -Wformat-security 會警告,建議禁用。
浮點精度陷阱
float 有效數字 ~7 位,double ~15 位
printf("%.10f", 1.0/3) 顯示 10 位但實際精度僅 6~7 位
- 財務計算請用整數分或定點庫
常見錯誤對照
| 錯誤代碼 | 問題 | 修正 |
printf("%d", 3.14); | 型別不符,未定義行為 | printf("%f", 3.14); |
printf("%s", 42); | 整數當字串指標 | printf("%d", 42); |
printf(buf); | 格式化字串漏洞 | printf("%s", buf); |
scanf("%s", buf); | 緩衝區溢位 | scanf("%99s", buf); |