文章目錄
- 一、結構體的使用
- 1. 結構體聲明
- 2. 變量創建與初始化
- 3. 特殊聲明與陷阱
- 二、內存對齊
- 1. 規則:
- 2. 示例分析:
- 3. 修改默認對齊數:
- 三、結構體傳參
- 四、結構體實現位段
- 1. 定義
- 2. 內存分配
- 3. 應用場景
- 4. 跨平臺問題:
- 5. 注意事項:
- 關鍵總結
一、結構體的使用
1. 結構體聲明
struct Stu { // struct 關鍵字 + 標簽(tag)char name[20]; // 成員變量int age; // 成員類型可不同char sex[5];char id[20];
}; // 分號不可省略
2. 變量創建與初始化
// 順序初始化
struct Stu s1 = {"張三", 20, "男", "20230818001"};// 指定成員初始化(C99+)
struct Stu s2 = {.age=18, .name="lisi", .id="20230818002", .sex="女"};
3. 特殊聲明與陷阱
· 匿名結構體(只能使用一次):
struct { int a; char b; } x; // 無標簽
struct { int a; char b; } *p;
p = &x; // 錯誤!編譯器認為兩者類型不同
· 自引用正確方式:
struct Node { // 錯誤:struct Node next;(無限遞歸)int data;struct Node* next; // 正確:使用指針
};
· typedef 陷阱:
typedef struct { // 錯誤:內部提前使用Nodeint data;Node* next; // ? 未定義
} Node;// 正確寫法
typedef struct Node {int data;struct Node* next;
} Node;
二、內存對齊
1. 規則:
· 首成員偏移量 = 0
· 其他成員對齊數 = min(編譯器默認對齊數, 成員大小)
· VS默認對齊數 = 8,Linux gcc無默認值(對齊數=成員大小)
· 結構體總大小 = 最大對齊數的整數倍
· 嵌套結構體:嵌套的結構體成員對齊到自身內部最大對齊數的整數倍處,結構體的整體大小是所有元素中最大對齊數的整數倍
2. 示例分析:
struct S1 { char c1; int i; char c2; }; // 大小=12 (1+3填充+4+1+3填充)
struct S2 { char c1; char c2; int i; }; // 大小=8 (1+1+2填充+4)
節省空間技巧:將小成員集中放置(對比S1 vs S2)
3. 修改默認對齊數:
#pragma pack(1) // 對齊數設為1(無填充)
struct S { char c1; int i; char c2; }; // 大小=6
#pragma pack() // 恢復默認對齊數
三、結構體傳參
· 傳地址優于傳結構體:
void print(struct S* ps) { // ? 推薦:傳遞指針(4/8字節)printf("%d\n", ps->num);
}
void print(struct S s) { // ? 避免:大結構體拷貝開銷大printf("%d\n", s.num);
}
原因:傳值導致拷貝開銷,降低性能。
四、結構體實現位段
1. 定義
位:二進制位(比特位)
struct A { // 位段聲明int _a:2; // 占2比特int _b:5; // 占5比特int _c:10; // 占10比特int _d:30; // 占30比特(不能超過自身大小,即<=32)
}; // 總大小:8字節(2個int)
· 成員主要為整形
2. 內存分配
· 空間按需以4字節(int)或1字節(char)開辟
· 給定空間后,成員在字節內的分配順序由編譯器決定(從左向右/從右向左)
· 當剩余空間不夠存儲一個成員時,剩余空間是浪費與否也取決于編譯器
3. 應用場景
. 如_a中只需要存儲0、1、2、3數字,則_a只需要兩個比特位的空間,避免空間的浪費
· 網絡協議頭(如IP數據報):
| 4位版本號 | 4位首部長度 | 8位服務類型 | 16位總長度 | ...
用位段精簡存儲(如4位版本號僅需半字節)
4. 跨平臺問題:
· int位段符號不確定(signed/unsigned)
· 最大位數依賴機器(16位機最大16,32位機最大32)
· 剩余位處理方式不確定(舍棄或利用)
5. 注意事項:
struct A sa;
scanf("%d", &sa._b); // ? 錯誤:位段成員無獨立地址
// 正確做法:
int b;
scanf("%d", &b);
sa._b = b;
關鍵總結
主題 要點
結構體聲明 分號不可省;避免匿名結構體自引用
內存對齊 掌握4條規則;通過成員排序節省空間;#pragma pack修改對齊數
傳參方式 首選傳地址(避免拷貝開銷)
位段 節省空間但不可移植;成員無地址;慎用于跨平臺程序
應用場景 協議封裝、硬件寄存器映射等空間敏感場景
注:位段內存分配示例(假設小端存儲):
struct S { char a:3; char b:4; char c:5; char d:4; };
struct S s = {0};
s.a = 10; // 二進制: 010 (存儲低3位)
s.b = 12; // 二進制: 1100 (存儲后續4位)
// 內存布局: | 1100 010 | ???? ??? | ... |