sprintf 與 sscanf 是 C 語言格式化輸入輸出的核心,本質上是「數字 ↔ 字符串」的編碼/解碼過程。本文通過內存十六進制分析,揭示其內部執行流程:取模除法分解數字、查碼表轉字符、ASCII 碼存儲、逆向解析累加還原數值。
char buf[10];
int i = 1234;
sprintf(buf, "%d", i);
// buf 內存:0x31 0x32 0x33 0x34 0x00 ('1','2','3','4','\0')
// strlen(buf) = 4
內部步驟:
n → 字符 '0' + n (即 0x30 + n)\0關鍵點:數值 1234 (0x04D2) 與字符串 "1234" (0x31323334) 內存表示完全不同。
int i = 0x1234;
sprintf(buf, "%x", i);
// buf 內存:0x31 0x32 0x33 0x34 ('1','2','3','4')
// 輸出 "1234"
步驟:除 16 取餘 → 十六進制數字 → 查碼表 → 存儲。結果字符串與 %d 1234 相同,但源數值不同(0x1234 vs 1234)。
n + '0')不同編碼(EBCDIC、GBK、UTF-8)下,相同數字轉字符串的二進制表示不同。
char buf[5] = "1234"; // 內存 0x31 0x32 0x33 0x34
int i;
sscanf(buf, "%d", &i);
// i = 1234
內部步驟:
ch - '0')val = val * 10 + digit(十進制)%d:按 10 進制累加%x:按 16 進制累加%o:按 8 進制累加相同字符串 "1234",用 %d 解析得 1234,用 %x 解析得 0x1234 (4660)。
int i = 100;
sprintf(buf, "%.2f", i); // ❌ 錯誤!棧上讀取 8 字節 double,實際只有 4 字節 int
sprintf(buf, "%.2f", (double)i); // ✅ 正確
變參函數無類型檢查,格式串與實際參數類型必須嚴格對應。
sprintf = 數字分解 + 碼表編碼 + 內存存儲;sscanf = 字符讀取 + 碼表解碼 + 進制累加。理解這一本質,有助於調試格式化漏洞、實現自定義序列化、跨平台數據交換。記住:數值內存 ≠ 字符串內存,碼表是橋樑,進制是規則。