C 語言提供兩種聚合類型:陣列 (同質元素集合) 與結構體 (異質成員集合)。結構體允許將不同型別的資料組織成邏輯整體,是建立複雜資料模型的基礎。
struct {
int a;
char b;
float c;
} x; // 建立變數 x,型別匿名
struct SIMPLE {
int a;
char b;
float c;
};
struct SIMPLE x; // 單一變數
struct SIMPLE y[20], *z; // 陣列與指標
typedef struct {
int a;
char b;
float c;
} Simple;
Simple x;
Simple y[20], *z;
> **跨檔案使用**:將 `typedef` 或 `struct TAG` 宣告放入標頭檔 (`.h`),其他來源檔 `#include` 即可共享型別定義。
struct Node { int data; struct Node *next; } node, *ptr = &node;
// 直接存取 (.):物件本身
node.data = 10;
node.next = NULL;
// 間接存取 (->):透過指標
ptr->data = 20; // 等同 (*ptr).data
ptr->next = &node;
struct SELF_REF {
int a;
struct SELF_REF *next; // 指標大小固定,編譯器可計算結構大小
int c;
};
struct ILLEGAL {
int a;
struct ILLEGAL next; // 錯誤:需要已知大小來計算大小
int c;
};
// 錯誤:型別名稱在宣告結束前不可見
typedef struct {
int a;
SELF_REF *next; // 編譯錯誤:SELF_REF 尚未定義
int c;
} SELF_REF;
// 正確:使用標籤前向宣告
typedef struct SELF_REF_TAG {
int a;
struct SELF_REF_TAG *next;
int c;
} SELF_REF;
struct B; // 前向宣告 (不完整型別)
struct A {
struct B *partner; // 合法:指向不完整型別的指標
// 其他成員...
};
struct B {
struct A *partner; // 此時 A 已完整定義
// 其他成員...
};
struct INIT_EX {
int a;
short b[10];
Simple c;
} x = {
10,
{1, 2, 3, 4, 5}, // 陣列部分初始化,其餘為 0
{25, 'x', 1.9} // 巢狀結構初始化
};
struct Point { int x, y; };
struct Point p = { .y = 10, .x = 5 }; // 順序無關,可讀性高
struct Node n = { .data = 42, .next = NULL };
struct ALIGN_DEMO {
char c; // offset 0, size 1
// 3 bytes padding
int i; // offset 4, size 4
double d; // offset 8, size 8 (8-byte aligned)
// 總大小 24 bytes (通常)
};
// 傳值:複製整個結構 (小型結構適用)
struct Point translate(struct Point p, int dx, int dy) {
p.x += dx; p.y += dy;
return p;
}
// 傳址:避免複製大型結構,允許修改原物件
void translate_inplace(struct Point *p, int dx, int dy) {
p->x += dx; p->y += dy;
}
| 錯誤模式 | 正確做法 | 原因 |
|---|---|---|
| `struct Node n; n.next = &n;` | 動態配置 `malloc` 建立節點 | 區域變數生命週期結束後指標失效 |
| 直接比較結構體 `a == b` | 逐成員比較或 `memcmp` | C 不支援結構體直接比較 (含填充位元組不確定) |
| 忽略對齊導致跨平台資料不相容 | 使用固定寬度型別 + `#pragma pack` 或序列化庫 | 不同編譯器/架構對齊規則不同 |
| 柔性陣列成員誤用 | C99: `struct { size_t len; char data[]; }` 末端唯一 | 需配合 `malloc(sizeof(struct) + len)` 使用 |
結構體是 C 語言建立抽象資料類型的核心機制。掌握宣告語法、記憶體模型、初始化方式與跨模組使用規範,能讓你設計出清晰、高效且可維護的系統級程式碼。