示例結構體定義
typedef struct {
int a;
short b[2];
} Ex2;
typedef struct EX {
int a;
char b[3];
Ex2 c;
struct EX *d;
} EX;
EX x = {10, "hi", {5, {-1, 25}}, 0};
EX *px = &x;
指針訪問機制
表達式 px 的左值與右值
- 右值:指針變量
px 本身的內容(即地址值)
- 左值:
px 的存儲位置,可被新地址值替換
px + 1 不是左值(非可識別內存位置),但若 px 指向結構體數組,其右值指向下一個結構體
間接訪問 *px
- 右值:整個結構體內容,可賦值給同類型變量、作為
. 操作符左操作數、傳遞給函數或作為返回值(但效率低)
- 左值:結構體存儲位置,可接受新值(即所有成員更新)
*px + 1 非法(結構體不支持與整數加法),但 *(px + 1) 合法(若為數組元素)
結構體內存佈局與對齊
- 編譯器按成員聲明順序分配內存
- 為滿足對齊要求,成員間可能插入填充字節
sizeof 返回包含填充字節的總大小
- 使用
offsetof(type, member)(需 <stddef.h>)獲取成員偏移量
示例:計算成員偏移
struct tiger {
char a;
int b;
char c;
};
int main() {
struct tiger x;
int m = offsetof(struct tiger, b); // 輸出 4(假設 int 4 字節對齊)
printf("%d\n", m);
return 0;
}
結構體作為函數參數:三種傳遞方式對比
typedef struct {
char product[20];
int quantity;
float unit_price;
float total_amount;
} Transaction;
| 方式 | 代碼示例 | 優點 | 缺點 |
| 值傳遞 | void print(Transaction t) | 簡單,函數內修改不影響原值 | 拷貝開銷大(示例 32 字節),效率低 |
| 指針傳遞 | void print(Transaction *t) | 僅傳指針(4/8 字節),效率高 | 函數可修改原值,需 const 保護 |
| 返回修改值 | float compute(Transaction t) | 避免返回整個結構體 | 仍需傳遞整個結構體,僅適用單值計算 |
最佳實踐:指針 + const
void print_receipt(const Transaction *trans) {
// 只讀訪問,編譯器防止誤修改
}
void compute_total(Transaction *trans) {
// 需修改時不加 const
trans->total_amount = trans->quantity * trans->unit_price;
}
總結
- 結構體是標量,支持賦值、傳參、返回值
- 大結構體傳參必須使用指針,配合
const 表達語義
- 理解內存佈局、對齊、偏移量,是底層優化與調試基礎
- 指針算術(
px+1)按結構體大小步進,是數組遍歷基礎