C语言结构体内二级指针如何通过自定义函数分配内存
核心原理
o->x的类型是struct xyz **,本质是用来维护一个struct xyz*类型的动态数组:数组的每个元素都是一个指向struct xyz的指针,数组本身的起始地址存放在o->x中。
你编写的hello函数的逻辑是:接收一个struct xyz**类型的地址,在函数内部把该地址指向的struct xyz*变量,赋值为新申请的struct xyz内存块的起始地址。
之前调用失败的根本原因
所有尝试的调用都没有把hello的写操作绑定到合法的内存区域上:
malloc完o之后,o内部的所有成员都是未初始化的野值,o->x本身不指向任何合法内存。hello(o->x+1)计算出的地址是基于野指针的偏移,属于非法内存区域,hello往这个位置写入malloc结果,不会更新o的任何成员。hello(*o->x+1)首先对野指针o->x做解引用操作,本身就是未定义行为,计算出的地址完全无效。
正确实现步骤
要实现通过o->x + 下标访问元素,需要按层级依次分配内存:
- 分配
o本身的内存(已完成)struct abc *o = (struct abc *)malloc(sizeof(struct abc)); - 给
o->x对应的指针数组分配连续内存
比如需要维护长度为N的指针数组,就要先把数组的内存申请出来,把起始地址赋值给o->x,并初始化所有元素为NULL:// 例如申请可以存放10个struct xyz*元素的数组 int arr_cap = 10; o->x = (struct xyz **)malloc(sizeof(struct xyz *) * arr_cap); memset(o->x, 0, sizeof(struct xyz *) * arr_cap); - 调用
hello为数组中的每个元素分配实际的struct xyz内存
传参时需要传入数组中对应下标的元素的地址:因为o->x[i]的类型是struct xyz*,它的地址类型正好是struct xyz**,完全匹配hello的形参要求。
上述写法和// 给0号下标对应的元素分配内存 hello(&o->x[0]); // 给1号下标对应的元素分配内存 hello(&o->x[1]);hello(o->x + 0)、hello(o->x +1)完全等价——因为数组下标访问o->x[i]的本质是*(o->x + i),因此&o->x[i]和o->x + i是同一个地址。
可直接编译运行的示例
#include <stdio.h> #include <stdlib.h> #include <string.h> // 提前定义依赖的结构体 struct xyz { int val; }; struct abc { struct xyz **x; }; void hello(struct xyz **xyz_obj) { *xyz_obj = (struct xyz *)malloc(sizeof(struct xyz)); (*xyz_obj)->val = 0; // 初始化避免野值 } int main() { // 1. 分配o本身的内存 struct abc *o = (struct abc *)malloc(sizeof(struct abc)); // 2. 给o->x分配长度为2的指针数组 o->x = (struct xyz **)malloc(sizeof(struct xyz *) * 2); memset(o->x, 0, sizeof(struct xyz *) * 2); // 3. 调用hello给每个下标分配内存 hello(o->x + 0); hello(o->x + 1); // 4. 下标访问验证 o->x[0]->val = 100; o->x[1]->val = 200; printf("x[0] = %d, x[1] = %d\n", o->x[0]->val, o->x[1]->val); // 内存释放 free(o->x[0]); free(o->x[1]); free(o->x); free(o); return 0; }
注意事项
- 如果需要在运行时动态扩展
o->x的数组长度,需要通过realloc调整o->x本身指向的内存块大小,不能直接给元素分配内存来实现扩展。 - 如果需要在函数内部修改
o->x本身的指向(比如在函数里重新分配数组内存),传给函数的参数需要使用三级指针struct xyz ***,因为要在函数中修改o内部x指针本身的值。 - 必须先给
o->x分配合法的数组内存,所有基于它的下标计算、地址偏移才是有意义的,否则所有操作都是未定义行为。
内容的提问来源于stack exchange,提问作者user786
相关产品推荐
相关产品推荐

