#include <stdio.h>
#include <math.h>
main() {
double a, b, i, j, s = 0;
printf("請輸入a和次數\n");
scanf("%d %d", &a, &j); // ❌ 錯誤:%d 對應 int*,實傳 double*
for (i = 0; i <= j; i++) {
b = pow(10, i);
s = s + a * b;
}
printf("s=%d\n", s); // ❌ 錯誤:%d 對應 int,實傳 double
}
現象:無論輸入什麼,s 輸出總是 0。
| 調用 | 格式符 | 期望類型 | 實際參數類型 | 後果 |
|---|---|---|---|---|
scanf("%d %d", &a, &j) | %d | int * | double * (8字節) | 只讀取 4 字節,高 4 字節未寫入/破壞棧,a/j 值亂 |
printf("s=%d\n", s) | %d | int | double (8字節) | 只取低 4 字節解釋為 int,通常為 0(IEEE 754 雙精度小數低位常為 0) |
| 類型 | scanf 輸入 | printf 輸出 | 備註 |
|---|---|---|---|
int | %d / %i | %d | |
unsigned int | %u | %u | |
long | %ld | %ld | |
long long | %lld | %lld | C99 |
float | %f / %e / %g | %f / %e / %g | printf %f 默認 6 位小數 |
double | %lf / %le / %lg | %f / %lf / %e / %g | scanf 必須 %lf;printf %f 也可(默認提升) |
long double | %Lf | %Lf | |
char (字符) | %c | %c | scanf 需跳過空白可用 %c |
char * (字符串) | %s | %s | scanf 不需 &,需防溢出用 %Ns |
void * (指針) | %p | %p | 標準輸出格式 |
double 輸入用 %lf、輸出用 %f 也行?float*(4B) 和 double*(8B),故 %f 對應 float*,%lf 對應 double*。float 自動提升為 double,故 %f、%lf、%e、%le 等**完全等價**處理 double 值。C99 規定 %lf 在 printf 合法且同 %f。-Wall -Wextra -Wformat=2 (GCC/Clang)、**絕對能報出** 此類不匹配。%lf 讀寫 double**:雖 printf 可用 %f,但統一 %lf 更清晰、不易混淆。printf("a=%lf, &a=%p\n", a, &a); 確認讀寫正確。本案例中 scanf("%d", &double_var) 只寫入 4 字節導致高位殘留垃圾值,printf("%d", double_var) 只讀低 4 字節解釋為 int 多為 0。**格式符與類型嚴格匹配是 C 語言 I/O 正確性的基石**,務必牢記 double → %lf、float → %f、int → %d、long long → %lld、指針 → %p,並開啟編譯器格式檢查警告。