float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;
long n5 = 250;
long n6 = 213;
printf("%ld %ld %ld %ld %ld %ld\n", n1, n2, n3, n4, n5, n6);
float 以 double 傳遞(佔 2 個 32 位棧槽 / 1 個 64 位寄存器)。%ld 告訴 printf「下一個參數是 long(整數)」。printf 讀整數寄存器,但浮點值在 XMM 寄存器 → 讀到垃圾值。float 壓 8 字節 (double),%ld 讀 4 字節 → 讀到 double 低 4 字節(通常為 0),棧指針錯位導致後續參數全部錯位。n5、n6 輸出不可預測(垃圾值、錯位值),屬於未定義行為 (UB)。| 類型 | 正確格式 | 說明 |
|---|---|---|
float/double | %f, %e, %g | float 自動提升為 double |
long | %ld | |
long long | %lld | |
int64_t | %" PRId64 " | 需 <inttypes.h> |
| 指針 | %p | 配合 (void *) |
-Wformat -Wformat-security(-Wall 含之)會報警:format '%ld' expects argument of type 'long int', but argument 1 has type 'double'。-Werror=format),編譯期攔截此類 Bug。printf 運行時無法感知實際參數類型,完全依賴格式字符串。調用者必須保證格式與實參類型一一對應。C 語言不提供運行時類型檢查,這就是「不安全」的根源。