將異構基本類型(int、float、char[] 等)按固定順序打包,形成新的類型模板,便於表達現實世界實體的多屬性特徵。
// 完整定義:帶標籤,可復用
struct Book {
int price;
char title[44];
};
// 定義同時聲明變量
struct Book { int price; char title[44]; } a, b;
// 匿名結構:無標籤,僅能在定義處聲明變量,不可復用
struct { int price; char title[44]; } c;
// 推薦:typedef 簡化類型名
typedef struct Book {
int price;
char title[44];
} Book;
Book b1, b2; // 直接用 Book
標籤作用:賦予類型身份,支援自我引用(鏈表節點)、跨文件聲明、避免匿名結構「同樣成員卻是不同類型」的問題。
// 順序初始化
Book b1 = { 43, "C Primer" };
// 指定初始化器 (C99) —— 順序無關、可選擇性初始化
Book b2 = { .title = "Modern C", .price = 59 };
Book b3 = { .price = 30 }; // title 自動歸零
// 嵌套結構初始化
typedef struct { int x, y; } Point;
typedef struct { Point center; int r; } Circle;
Circle c = { .center = {10, 20}, .r = 5 };
b2 = b1; 執行逐字節拷貝(淺拷貝)。b2 = {.price=10}; 僅在初始化時合法,C23 才引入複合字面量賦值。Book *p = &b1; p->price = 99;。
Book b = {10, "Test"};
Book *p = &b;
b.price; // 1. 直接訪問
p->price; // 2. 指針解引用訪問(最常用)
(*p).price; // 3. 顯式解引用後訪問
// 結論:p->m 等價於 (*p).m,前者語法糖更簡潔。
struct Demo {
char c; // 偏移 0
int i; // 偏移 4 (對齊填充 3 字節)
double d; // 偏移 8 (對齊填充 0 字節,假設 8 字節對齊)
};
// sizeof(Demo) = 24 (尾部填充至最大對齊倍數)
#pragma pack(n) 或屬性 `__attribute__((packed))` 可壓縮佈局(網絡協議、硬體寄存器映射常用),但可能降低訪問速度或觸發硬體異常。static)必須用常量表達式初始化。
struct Packet {
int len;
char data[]; // 末端不定長數據
};
// 分配:malloc(sizeof(struct Packet) + payload_len)
// 訪問:pkt->data[i]
實現變長結構體,單次分配、連續記憶體、無指針間接開銷。
typedef struct Tag { ... } Type; 定義可復用類型。offsetof 宏檢查偏移。data[],而非 data[0](GCC 擴展)或指針。