問題描述
第一段位于LCD.h和LCD.c中,
? ? ? ? 定義個一個結構體lcd_params,并直接給與指針名*p_lcd_params;
我發現我在調用這個結構體時,即在LCD.c中,使用指針類型定義的
static p_lcd_params p_array_lcd[LCD_NUM];
static p_lcd_params g_p_lcd_selected;.
并且可以正常運行
第二段代碼位于Timer.c中
????????定義個一個結構體timer_desc,給與指針名ptimer_desc;
我在調用這個結構體時,使用指針類型會有錯誤,只能使用結構體名定義
timer_desc timer_arry[Timer_NUM];
//LCD.H
typedef struct lcd_params
{
xxxxx
} lcd_params, *p_lcd_params;//LCD.C
static p_lcd_params p_array_lcd[LCD_NUM];
static p_lcd_params g_p_lcd_selected;int register_lcd(p_lcd_params plcd)
{int i;for (i = 0; i < LCD_NUM; i++){if (!p_array_lcd[i]){p_array_lcd[i] = plcd;return i;}}return -1;
}
typedef void (*timer_func)(void);
typedef struct timer_desc
{char *name;timer_func fp;
} timer_desc, *ptimer_desc;timer_desc timer_arry[Timer_NUM];int register_timer(char *name, timer_func fp)
{int i;for (i = 0; i < Timer_NUM; i++){if (!timer_arry[i].fp){timer_arry[i].name = name;timer_arry[i].fp = fp;return 0;}}return -1;
}
問題原因:
在第一段代碼中,我在使用p_array_lcd[i]時,在外部調用 register_lcd
的時候傳入了結構體的地址:即這個函數他傳入了一個結構體地址
int register_lcd(p_lcd_params plcd)?
lcd_params my_lcd = { ... };
register_lcd(&my_lcd); ?// 傳入結構體地址
而在我的第二段代碼中,我并沒有為這個結構體指針分配地址。而如果他要是用指針的話
需要使用malloc來為結構體分配內存,或者按照第一種來為他傳入結構體地址。
timer_arry[i] = (ptimer_desc)malloc(sizeof(timer_desc));
3:訪問方式問題
如果使用指針來定義的話,在訪問結構體內部元素時,要使用->來訪問
ptimer_desc timer_arry[Timer_NUM]; ?// 一個結構體指針數組
timer_arry[i]->fp ? // 正確 ?
timer_arry[i]->name // 正確 ?
不使用結構體來定義的話,使用.來訪問結構體元素
timer_desc timer_arry[Timer_NUM]; ?// 一個結構體指針數組
timer_arry[i].fp ? // 正確 ?
timer_arry[i].name // 正確 ?
4:第一類代碼不使用結構體指針
這個表示:數組中每個元素是一個指向 lcd_params
結構體的指針。你可以在別處創建結構體,然后通過 &
傳入:
static p_lcd_params p_array_lcd[LCD_NUM]; // 數組元素是結構體指針
lcd_params lcd1 = { ... }; register_lcd(&lcd1); // ? 傳入地址,存入指針數組
如果不使用指針,而是改成結構體數組?
static lcd_params lcd_array[LCD_NUM]; // 數組元素是結構體本體 static int lcd_count = 0;
然后
register_lcd
函數可以這樣寫:
int register_lcd(lcd_params *plcd)
{
if (lcd_count >= LCD_NUM)
return -1;
lcd_array[lcd_count] = *plcd; // 拷貝整個結構體
return lcd_count++;
}
這樣做的優點:
-
不需要動態分配內存(malloc),更簡單、更安全。
-
所有結構體數據都存儲在本地數組中,便于統一管理。
-
避免指針懸空、內存泄漏等問題。
這樣做的缺點:
-
結構體會被拷貝一次,如果結構體很大(比如包含字符串、數組等),效率會略低。
-
如果你希望多個地方共享同一個結構體的數據,就做不到了,因為你拷貝的是副本。
-
結構體中如果有
char *
或void *
成員,還要小心淺拷貝問題(拷貝指針但不是數據本體)。
🆚 指針 VS 非指針對比總結:
項目 | 使用結構體指針 | 不使用結構體指針(結構體數組) |
---|---|---|
內存管理 | 需自己分配、釋放(可能內存泄漏) | 編譯期靜態分配,自動管理 |
數據共享 | 可在多個模塊間共享同一結構體 | 是拷貝副本,無法共享 |
拷貝開銷 | 拷貝指針,開銷小 | 拷貝整個結構體,開銷可能更大 |
安全性 | 易出錯(空指針、懸空指針) | 更安全,邏輯更直觀 |
靈活性 | 靈活,可實現動態注冊、釋放等功能 | 結構固定,適合數據量已知、場景簡單 |