int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);
n-1 字元,結尾自動補 \0,緩衝區大小為 n 時不會溢位。n,表示被截斷。char str[10] = {0};
snprintf(str, sizeof(str), "0123456789012345678");
printf("str=%s\n", str); // 輸出: 012345678 (9字元 + \0)
char str[10] = {0};
snprintf(str, 18, "0123456789012345678"); // n=18 > sizeof(str)=10
printf("str=%s\n", str); // 未定義行為!可能緩衝區溢位
char str1[10] = {0}, str2[10] = {0};
int ret1 = snprintf(str1, sizeof(str1), "%s", "abc"); // 完整寫入
int ret2 = snprintf(str2, 4, "%s", "aaabbbccc"); // 截斷
printf("ret1=%d, str1=%s\n", ret1, str1); // ret1=3, str1=abc
printf("ret2=%d, str2=%s\n", ret2, str2); // ret2=9, str2=aaa
ret1=3:實際寫入 3 字元,等於欲寫入長度。ret2=9:欲寫入 9 字元 (aaabbbccc),但緩衝區僅 4 位元組 (含 \0),實際寫入 aaa\0,回傳 9 提示被截斷。char dst[10] = {0};
char src1[] = "aaa";
char src2[] = "aaabbbcccddd";
int ret1 = snprintf(dst, sizeof(dst), "str:%s", src1); // "str:aaa" (7字元) OK
int ret2 = snprintf(dst, sizeof(dst), "str:%s", src2); // 欲寫 15 字元,截斷為 "str:aa"
printf("ret1=%d, ret2=%d\n", ret1, ret2); // 7, 15
| 錯誤寫法 | 問題 | 修正 |
|---|---|---|
| snprintf(buf, len, fmt, ...); // len 為字串長度而非緩衝區大小 | 若 len > sizeof(buf) 導致溢位 | snprintf(buf, sizeof(buf), fmt, ...); |
| 忽略回傳值 | 無法偵測截斷 | 檢查 ret >= sizeof(buf) 判斷是否截斷 |
| 重疊緩衝區 | 未定義行為 | 確保 src 與 dst 不重疊 |
snprintf 是 C/C++ 格式化字串的安全基石。核心原則:**永遠傳入 `sizeof(buffer)` 作為 `n`**,並**檢查回傳值是否 ≥ `sizeof(buffer)`** 以偵測截斷。嚴禁手動指定超過緩衝區大小的 `n`。