typedef 是 C 語言的儲存類別關鍵字 (儘管不影響儲存屬性),用於為現有資料類型建立一個新的別名。它不建立新類型,只是讓程式碼更具可讀性、可移植性與維護性。
typedef 現有類型 新類型名;
// 等價於:使用 新類型名 宣告變數,效果同 現有類型
// 函數指標:原寫法極難閱讀
int (*compare)(const void *, const void *);
// 使用 typedef
typedef int (*CompareFunc)(const void *, const void *);
CompareFunc cmp = my_compare_func; // 清晰易懂
// 陣列指標
typedef int (IntArray10)[10];
IntArray10 arr; // 等同於 int arr[10];
// C 風格:宣告變數需加 struct
struct Student { char name[20]; int id; };
struct Student s1; // 必須寫 struct
// typedef 風格:一次定義,終身受益
typedef struct Student {
char name[20];
int id;
} Student; // 標籤名與類型名同名,慣例大寫首字母
Student s2; // 直接使用 Student,像內建類型一樣
// 甚至可匿名結構體:
typedef struct { double x, y; } Point;
Point p1 = {1.0, 2.0};
標準庫 <stdint.h> (C99) 大量使用 typedef 定義固定寬度整數:
// 在 32 位系統可能是
typedef int int32_t;
typedef long int64_t;
// 在 64 位系統可能是
typedef long int32_t; // 假設 long 是 32 位
typedef long long int64_t;
應用層程式碼只用 int32_t,重新編譯即可跨平台,無需修改業務邏輯。
// 定義回調類型
typedef void (*EventCallback)(int event_id, void *user_data);
// 註冊介面
void register_event(EventCallback cb, void *data);
// 實現
void on_click(int id, void *data) { printf("Event %d\n", id); }
register_event(on_click, NULL);
| 特性 | typedef | #define |
|---|---|---|
| 處理階段 | 編譯階段 (語義分析) | 預處理階段 (文字替換) |
| 型別檢查 | 編譯器支援,型別安全 | 無,純文字替換 |
| 指標宣告 | typedef int* IntPtr; IntPtr a, b; (a,b 皆為 int*) | #define IntPtr int* IntPtr a, b; (a 是 int*, b 是 int!) |
| 作用域 | 遵循 C 作用域規則 (區塊/檔案) | 全域從定義處到檔案結束 |
| 除錯資訊 | 保留類型名,除錯器可識別 | 替換後消失,除錯器見原始類型 |
結論:定義類型別名請永遠使用 typedef,拒絕 #define。
在頭檔中僅前向宣告 typedef struct HiddenImpl *Handle;,實現細節隱藏在 .c 檔中,達到資訊隱藏與編譯防火牆效果。
typedef 是 C 語言類型系統的「語法糖」,善用它能讓程式碼自文檔化、屏蔽平台差異、簡化複雜宣告。掌握 typedef 與 #define 的本質區別,是進階 C 程式設計師的必修課。