三種定義方式
1. 僅定義型別
struct Stuff {
char job[20];
int age;
float height;
};
2. 同時宣告變數
struct Stuff {
char job[20];
int age;
float height;
} huqinwei; // 等同於 struct Stuff huqinwei;
3. 匿名結構體(單次使用)
struct {
char job[20];
int age;
float height;
} huqinwei; // 無法再宣告同型別變數
變數初始化與賦值
// 指定初始化器 (C99)
struct Stuff s1 = {.job = "manager", .age = 30, .height = 185.0f};
// 整體賦值(逐成員複製)
struct Stuff s2 = s1;
成員存取
s.age:物件直接存取
p->age:指標存取((*p).age 簡寫)
指標與動態記憶體
struct Stuff *p = malloc(sizeof(struct Stuff));
p->age = 25;
free(p);
陣列與巢狀結構
// 含陣列的結構體
struct Test { int a[3]; int b; };
struct Test arr[3] = { {{66,77,55},0}, {{44,65,33},0}, {{46,99,77},0} };
// 巢狀結構
struct A {
struct B { int c; } b;
struct B sb; // 同型別第二個成員
} a;
a.b.c = 11; a.sb.c = 22;
結構體與函數傳遞
// 傳值:複製整個結構體(小型結構體適用)
void by_value(struct A a) { printf("%d\n", a.b.c); }
// 傳指標:避免複製、可修改原值(大型結構體適用)
void by_ptr(struct A *a) { printf("%d\n", a->b.c); }
int main() {
struct A a = { .b = {.c = 112} };
by_value(a);
by_ptr(&a);
}
記憶體佈局與大小
sizeof(struct) = 所有成員大小總和 + 為了對齊的填充位元組
- 結構體定義本身不佔用資料區記憶體(屬於型別資訊)
- 不能有柔性陣列成員(
char data[])除非為最後一個成員且 C99
- 不能在定義中給成員預設值(C++ 才支援)
對齊範例
struct Align {
char c; // 1 byte
// 3 bytes padding
int i; // 4 bytes
// 可能無 padding
double d; // 8 bytes (需 8-byte 對齊)
};
// sizeof 可能為 24 (而非 13)
常見錯誤
- 忘記結構體定義結尾的
;
- 柔性陣列成員不在結尾
- 結構體賦值時指標成員淺拷貝導致雙重釋放
- 傳遞大型結構體給函數未用指標,效能差