printf 族函數是 C 語言最常用的輸出工具,其格式字符串雖然簡潔,但功能極其強大,掌握其完整語法能讓輸出控制得心應手。本文系統梳理格式控制字符串的各組成部分、常用轉換符、標誌、寬度精度及進階用法,並附帶實戰示例。
一個完整的格式說明符結構如下:
%[標誌][最小寬度][.精度][長度修飾符]轉換符
| 標誌 | 含義 |
|---|---|
- | 左對齊(默認右對齊) |
+ | 有符號數值總是顯示符號(+ 或 -) |
空格 | 正數前加空格,負數顯示 - |
# | 替代形式:八進制加 0,十六進制加 0x,浮點數強制顯示小數點 |
0 | 數值右對齊時左側填充 0 而非空格 |
* 表示,由對應參數動態傳入(如 %*.*s)。| 修飾符 | 適用類型 | 含義 |
|---|---|---|
hh | 整數 | signed char/unsigned char |
h | 整數 | short/unsigned short |
l | 整數/浮點 | long/unsigned long;double(scanf專用) |
ll | 整數 | long long/unsigned long long |
L | 浮點 | long double |
z | 整數 | size_t (C99) |
t | 整數 | ptrdiff_t (C99) |
j | 整數 | intmax_t (C99) |
| 轉換符 | 輸出類型 | 示例/說明 |
|---|---|---|
d, i | 有符號十進制整數 | %d, %5d, %05d |
u | 無符號十進制整數 | %u, %lu |
o | 無符號八進制 | %o, %#o (帶前綴 0) |
x, X | 無符號十六進制 | %x (小寫), %#X (大寫帶 0X) |
f, F | 十進制浮點數 | %f (6位小數), %8.2f |
e, E | 科學計數法 | %e (1.23e+03), %10.3E |
g, G | 自動選擇 f/e 短者 | 不輸出無意義尾隨 0 |
a, A | 十六進制浮點數 (C99) | %a (0x1.23p+4) |
c | 單字符 | %c |
s | 字符串 | %s, %10s, %-10.5s |
p | 指針地址 | %p (實現定義格式) |
n | 寫入已輸出字符數 | %n (需指針參數,C99 起因安全風險常被禁用) |
%% | 輸出字面 % | %% |
int w = 10, p = 4;
printf("%*.*f\\n", w, p, 3.14159); // 相當於 %10.4f
%[...](僅 scanf/sscanf)%[a-z]:匹配 a-z 任意字符(貪婪)%[^\\n]:匹配非換行符任意字符(讀整行)%*[^=]=%s:跳過 = 前內容,讀取後續字符串printf("進度: %d%%\\n", 50); // 輸出 50%
printf("路徑: C:\\\\Windows\\n"); // 雙重轉義
%f 對應 double,float 會自動提升;%ld 必須傳 long,傳 int 會導致未定義行為。%s 要求以 \\0 結尾,否則越界讀取。snprintf 替代 sprintf,指定緩衝區大小。float 約 7 位有效數字,double 約 15-16 位;超出精度輸出無意義。%n 安全風險:攻擊者可利用格式化字符串漏洞任意寫內存,現代編譯器默認禁用或需顯式啟用。printf 格式系統雖老舊,但表達力極強。熟練掌握標誌、寬度、精度、長度修飾符與轉換符的組合,配合 * 動態參數與掃描集合,能優雅處理絕大多數文本輸出/解析需求。記住:類型匹配是安全前提,邊界檢查是健壯保障。