问题描述
第一段位于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 非指针对比总结:
项目 | 使用结构体指针 | 不使用结构体指针(结构体数组) |
---|---|---|
内存管理 | 需自己分配、释放(可能内存泄漏) | 编译期静态分配,自动管理 |
数据共享 | 可在多个模块间共享同一结构体 | 是拷贝副本,无法共享 |
拷贝开销 | 拷贝指针,开销小 | 拷贝整个结构体,开销可能更大 |
安全性 | 易出错(空指针、悬空指针) | 更安全,逻辑更直观 |
灵活性 | 灵活,可实现动态注册、释放等功能 | 结构固定,适合数据量已知、场景简单 |