main() {
int i;
char *f="%12.8s\n", *s="*******";
for(i=1; i<9; i++) {
*(f+2)=2+i-1+'0'; // 修改寬度數字
*(f+4)=8-i+1+'0'; // 修改精度數字
printf(f, s);
}
}
初始 f 指向字符串常量區(不可寫!):
f → ['%','1','2','.','8','s','\n','\0']
0 1 2 3 4 5 6 7
⚠️ 致命錯誤:字符串字面量存放在只讀段,*(f+2)=... 導致未定義行為(段錯誤/運行時崩潰)
修正:char f[] = "%12.8s\n"; // 放在棧上,可修改
| i | f[2] (寬度十位) | f[4] (精度) | 格式化字符串 | 輸出效果 |
|---|---|---|---|---|
| 1 | '2' | '8' | %12.8s | 取前8字符,寬12右對齊 |
| 2 | '3' | '7' | %13.7s | 取前7字符,寬13右對齊 |
| 3 | '4' | '6' | %14.6s | 取前6字符,寬14右對齊 |
| ... | ... | ... | ... | ... |
| 8 | '9' | '1' | %19.1s | 取前1字符,寬19右對齊 |
*******
*******
*******
*******
*******
*******
*******
*******
實際為右對齊的等腰三角形,每行星號遞減1,前置空格遞增1。
// 更清晰、安全、可維護
for (int i = 1; i < 9; i++) {
int width = 11 + i; // 12,13,14...
int precision = 9 - i; // 8,7,6...
printf("%*.*s\n", width, precision, s);
}
// %*.*s 寬度和精度由參數傳入,無需構造格式字符串
原代碼是「指針修改只讀內存」的未定義行為。修正後展示了C語言格式化輸出的動態能力,但生產代碼請使用`%*.*s`參數化寫法。