1. void* 不能參與算術運算
原因:指標運算需要知道所指物件大小(sizeof(*ptr)),void* 無型別資訊,無法計算步長。
僅允許:賦值、比較、sizeof、轉型為具體型別後再運算。
2. & 不能用於非左值
- 字面常數無位址(存於符號表)。
- 陣列名為常量指標(
int *const a),不可修改。
- 等價關係:
int a[10]; → int *const a;
int b[3][4]; → int (*const b)[4];
3. return 0 vs exit(0)
| 項目 | return 0 | exit(0) |
| 層級 | 語言級(函數返回) | 系統調用級(進程終止) |
| 控制權 | 交回呼叫者 | 交回作業系統 |
| 清理動作 | 僅當前函數棧框 | 全進程:關閉檔案、釋放記憶體、調用 atexit 登記函數 |
| main 中 | 等價於 exit(0) | 直接終止 |
4. static 減少命名衝突
static int a; 限制於本編譯單元(檔案)可見。
- 多檔案各自定義
static int a 不衝突。
- 函數前加
static 同理,僅本檔可見。
5. setbuf 自訂輸出緩衝區陷阱
// 錯誤:buf 為區域陣列,main 結束前釋放,運行時庫清理時訪問野指標
char buf[BUFSIZ]; setbuf(stdout, buf);
三種修正:
static char buf[BUFSIZ];
- 移至檔案域(全域/靜態)。
setbuf(stdout, malloc(BUFSIZ)); 動態分配,不主動釋放。
6. 多維陣列參數:首維可省,其餘必須給出
- 編譯器計算位址需要知道「列數」(跨度),不需要知道行數。
void f(int a[][3]); 合法;void f(int a[2][]); 非法。
- C 不做越界檢查,故首維資訊對編譯器無用。
7. 多維陣列下標等價轉換
a[i][j] == *(a[i] + j) == (*(a + i))[j] == *(*(a + i) + j)
8. 下標運算子語義:返回元素左值
a[3] = 100; // 等價於
int &ri = a[3]; ri = 100; // C++ 參考語義說明
9. 動態分配多維陣列:必須用「指向陣列的指標」接收
char *q = new char[5]; // 一維
char (*p)[4] = new char[5][4]; // 二維:p 型別為 char(*)[4]
delete [] p; // 釋放
10. 標號與作用域解析
- 標號(
label:)擁有函數作用域,函數內任意處可 goto label;。
- 區域變數遮蔽全域同名變數,可用
::a(C++)或重構避免同名。
- 上一篇文章: Erlang 與 C 節點通訊實戰:erl_interface 構建 CNode 完整教學
- 下一篇文章: C 語言實作:4×4 矩陣最大最小值與座標、雙主對角線元素和
Copyright ©
程式碼之家 All Rights Reserved