以下制作可变大小结构的方法有什么问题?
struct tode{
int g;
int *p;
};
struct tode *lp = malloc(sizeof(struct tode) + (10 * sizeof(int)));
注意:这是完全错误的,但在我脑海中引起了混乱,所以试图讨论
答案 0 :(得分:3)
p
是指向int
的指针,而不是数组。所以它不会编译。您应该使用零长度数组或灵活数组成员为它动态分配内存。但是,它必须是最后一个结构成员。以下是您如何申报。
struct tode {
int g;
int p[]; // p is a zero length array here, not a pointer
};
// sizeof(tode) is 4 on a 32-bit machine
这是少数可以声明零长度数组的情况之一(其他我记得当你声明一个extern
数组时)。由于零长度成员是不完整类型,因此必须先分配内存,然后才能对其进行任何操作。
struct tode *lp = malloc(sizeof(tode) + 10*sizeof(int));
// after you are done with lp
free(lp);
这里,10*sizeof(int)
参数中的malloc
部分动态分配数组。 sizeof(tode)
未考虑p
因为它是不完整的类型。
在上述声明之后,p
是一个包含10 int
s。
但是,如果你这样做了
struct tode {
int g;
int *p; // p is a pointer
};
// sizeof(tode) is 8 on a 32-bit machine
然后你会动态地将结构分配为
struct tode *lp = malloc(sizeof(tode));
// lp->p is of type (int *) so it can contain any int address
lp->p = malloc(10 * sizeof(int));
// after you are done with lp
free(lp->p);
free(lp);
您还可以使用designated initializer(C99)在堆栈上分配和初始化您的结构,如Jens所示
struct tode lv = {.g = 10, .p = malloc(10 * sizeof(int))};
但是,在变量lv
超出范围之前,您应free
将lv.p
指向的内存free(lv.p);
作为
{{1}}
答案 1 :(得分:2)
您有lp
作为auto
变量,因此您无法为其分配新地址,lp
本身不是指针。正确的初始化如下所示:
struct tode lp = { .p = malloc(sizeof(int[10])) };
这不是struct
hack,只是一个普通的指针成员。既然你无论如何处理这个地址,就没有办法让这个连续。
BTW:struct
hack不是“ hack ”,它是C标准(正弦C99)的一部分,称为“灵活数组成员”。
答案 2 :(得分:0)
如果要使变量缓冲区结构使用数组作为最后一个元素而不是指针。或者适当地分配指针变量的地址,使其指向已分配的内存。
例如,您的代码p
将具有任意随机值。但是你希望它是lp + sizeof(lp->g)
(为了简单起见,请保留任何填充问题)。
因此,您应该将其定义为,并根据需要扩展p
。
struct tode{
int g;
int p[1];
};