首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言經典謎題與陷阱深度解析:從浮點數輸出到 sizeof 誤區

     編輯:關於C語言

謎題 1:float 用 %d 輸出會怎樣?


float a = 12.5f;
printf("%d\n", a);        // 輸出 0
printf("%d\n", (int)a);   // 輸出 12
printf("%d\n", *(int*)&a); // 輸出 1095237632

深度解析

  • 第 1 行:`printf` 非類型安全。`float` 傳參時自動提升為 `double`(8 位元組)。`%d` 期待 4 位元組 `int`,讀取 `double` 記憶體前 4 位元組。12.5 的 IEEE 754 double 表示為 `0x4029000000000000`,小端序記憶體前 4 位元組全為 0 → 輸出 0。
  • 第 2 行:`(int)a` 正確轉型為整數 12。
  • 第 3 行:`*(int*)&a` 直接以 `int*` 讀取 `float` 記憶體。12.5f 的 IEEE 754 為 `0x41480000` = 1095237632。

教訓:`printf` 格式字串必須與實際參數類型嚴格匹配。這也是 C++ 引入 `iostream` 型別安全機制的原因。

謎題 2:字串字面量的下標交換律


"hello"[2] == 2["hello"]  // 皆為 'l'

因為 `a[b]` 等價於 `*(a+b)`,加法交換律成立。

謎題 3:八進制字面量陷阱


int a = 010;  // 八進制 = 十進制 8
int b = 09;   // 編譯錯誤:9 非八進制數字

C 標準:以 0 開頭的整數字面量為八進制。

謎題 4:sizeof 不是函數


int i = 0;
sizeof(i++);  // 不會執行 i++,i 仍為 0
// sizeof 是編譯期運算子,僅計算類型大小

謎題 5:switch-case 中的變量初始化不會執行


switch(x) {
    int val = 10;  // 跳過初始化!
    case 1: val = 20; break;
}

案例標籤會跳過聲明語句,導致未初始化變量。解決:用 `{}` 包裹案例塊。

謎題 6:printf 回傳值


int cnt = printf("Hello"); // cnt = 5(輸出字符數)

謎題 7:stdout vs stderr 緩衝差異

  • `stdout`:行緩衝(遇 `\n`、滿、flush 輸出)
  • `stderr`:無緩衝(立即輸出)

除錯輸出請用 `stderr` 或 `fflush(stdout)`,否則程式崩潰前輸出可能丟失。

謎題 8:結構體對齊與 sizeof


struct { char c; int i; } s;  // sizeof 通常為 8(非 5)
// 編譯器插入填充位元組對齊 int

謎題 9:字串字面量不可修改


char *p = "hello";
p[0] = 'H'; // 未定義行為(可能崩潰)
// 正確:char p[] = "hello";

謎題 10:整數提升與有號無號比較


unsigned int u = 10;
int i = -1;
if (u > i) printf("true"); // 輸出 true!-1 提升為巨大無號數

總結:避坑指南

  1. 格式字串嚴格匹配參數類型
  2. 記住 `sizeof` 編譯期計算,不求值運算元
  3. switch 中變量初始化用 `{}` 隔離
  4. 除錯輸出用 `stderr` 或 `fflush`
  5. 字串字面量視為 `const`
  6. 有號無號混合運算警惕隱式轉換
  7. 啟用編譯器警告(`-Wall -Wextra -pedantic`)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved