// 方式 1:定義結構體同時宣告指標變數
struct String {
char name[8];
char sex[2];
int age;
char addr[40];
} *student;
// 方式 2:先定義結構體標籤,再宣告指標(推薦)
struct String {
char name[8];
char sex[2];
int age;
char addr[40];
};
struct String *student; // 清楚分離型別定義與變數宣告
-> 運算子student->name 等價於 (*student).name,前者為語法糖,更符合直覺。
strcpy(student->name, "Lu G.C");
student->age = 18;
結構體指標僅存放地址,指向的記憶體必須顯式分配:
#include
student = (struct String *)malloc(sizeof(struct String));
if (student == NULL) {
// 處理配置失敗
exit(1);
}
// 使用結構體...
free(student); // 釋放記憶體
student = NULL; // 防止懸空指標
關鍵點:
sizeof(struct String) 自動計算含對齊填充的總大小malloc 返回 void*,C 語言隱性轉換為目標指標型別NULL,必須檢查| 情境 | 結構體變數 | 結構體指標 |
|---|---|---|
| 宣告 | struct String s; | struct String *p; |
| 取首地址 | &s(變數名不是地址) | p 本身即地址 |
| 成員存取 | s.name | p->name |
| 指標運算 | 不支援 | p+1 跳過整個結構體大小 |
| 錯誤 | 後果 | 修正 |
|---|---|---|
| 未初始化直接解參考 | 未定義行為,程式崩潰 | 宣告時初始化 = NULL,使用前檢查 |
malloc 未檢查返回值 | 後續解參考導致崩潰 | 永遠檢查 if (ptr == NULL) |
釋放後未置 NULL | 懸空指標,重複釋放風險 | free(ptr); ptr = NULL; |
| 釋放非堆疊記憶體 | 堆破壞 | 只 free 對應 malloc/calloc/realloc 的指標 |
| 結構體變數名當指標用 | 編譯錯誤或邏輯錯誤 | 記住:結構體變數名不是地址,取址用 & |
// 修改呼叫者的結構體內容
void initStudent(struct String *s, const char *name, int age) {
strcpy(s->name, name);
s->age = age;
}
int main() {
struct String *stu = malloc(sizeof(*stu));
initStudent(stu, "Alice", 20); // 傳遞指標,避免複製大型結構體
free(stu);
}
傳遞指標而非結構體值,優勢:
結構體指標是 C 語言操作複雜資料結構的核心工具。掌握 -> 存取、malloc/free 生命週期管理、函數傳址參數三大核心,並養成「初始化、檢查、釋放置空」的防衛式編程習慣,能避開 90% 的指標相關 Bug。