初學 C/C++ 時,常混淆「結構體變數」與「結構體指標」在記憶體分配上的差異,導致 malloc 參數傳錯,造成記憶體越界或邏輯錯誤。以下釐清關鍵觀念。
typedef struct node {
int a;
int b;
} Node, *ANode;
Node P; // 宣告結構體變數(物件實例)
ANode Q; // 宣告指向結構體的指標
// 錯誤 1:嘗試將 malloc 回傳的指標指派給非指標變數 P
P = (Node*)malloc(sizeof(Node)); // 編譯錯誤:無法將 Node* 指派給 Node
// 錯誤 2:sizeof 運算對象錯誤
Q = (ANode)malloc(sizeof(ANode)); // 只分配了指標大小(4/8 bytes),非結構體大小
sizeof(ANode) 等同 sizeof(Node*),僅是指標大小(32 位元 4 bytes,64 位元 8 bytes),遠小於結構體實際大小,後續存取會導致記憶體越界。// 為指標 Q 分配正確大小的記憶體
Q = (ANode)malloc(sizeof(Node)); // 或 sizeof(*Q)
// 使用後記得釋放
free(Q);
| 宣告方式 | 意義 | sizeof 運算結果 | malloc 參數 |
|---|---|---|---|
Node P; | 在堆疊分配一個結構體實例 | 結構體大小(含對齊) | 不需 malloc,自動管理 |
ANode Q; / Node* Q; | 在堆疊分配一個指標變數 | 指標大小(4/8 bytes) | 需 malloc(sizeof(Node)) 配置堆積記憶體 |
Node* ptr = malloc(sizeof(*ptr)); 寫法,若未來型別變更,sizeof(*ptr) 會自動適應,減少維護錯誤。new Node() / delete,並搭配智慧指標(unique_ptr, shared_ptr)管理生命週期。搞懂「物件大小」與「指標大小」的區別,是寫出穩健 C/C++ 程式的基石。