如何使用 malloc 动态声明结构中存在的数组
Posted
技术标签:
【中文标题】如何使用 malloc 动态声明结构中存在的数组【英文标题】:How to dynamically declare a array present inside a structure using malloc 【发布时间】:2012-01-31 18:42:09 【问题描述】:我的程序中目前有以下代码:
struct mystruct
int x;
struct y *list[10];
mystruct *h1=(mystruct *)malloc(sizeof(mystruct));
我想在声明结构时动态声明数组list
(使用malloc()
)。谁能告诉我该怎么做?
【问题讨论】:
我可以建议使用#define 或 const 作为列表大小。当您需要更改它时,您会感谢我... 在我的程序中的某个时刻,我必须重新调整数组的大小。这就是为什么我不能使用#define 或 const。 @hektor 那么你不应该在你的struct
中保持不变。做struct y **list
。
【参考方案1】:
您需要明确地执行此操作。我通常使用这样的包装器函数来执行此操作。
编辑:现在底部有一个完整的工作示例。
struct mystruct *mystruct_init()
struct mystruct *mystruct = calloc(1, sizeof(*mystruct));
// loop through and allocate memory for each element in list
for (int i = 0; i < 10; i++)
mystruct->list[i] = calloc(1, sizeof(*(mystruct->list[i])));
return mystruct;
这样,您只需在代码中调用它:
struct mystruct *h1 = mystruct_init();
您还需要编写相应的mystruct_free()
函数。
这是一个工作示例(对我而言):
#include <stdlib.h>
#include <stdio.h>
struct y
int a;
;
struct mystruct
int x;
struct y **list;
int list_length;
;
struct mystruct *mystruct_init()
struct mystruct *mystruct = calloc(1, sizeof(*mystruct));
// loop through and allocate memory for each element in list
mystruct->list_length = 10;
mystruct->list = calloc(1, sizeof(struct y *) * mystruct->list_length);
for (int i = 0; i < mystruct->list_length; i++)
mystruct->list[i] = calloc(1, sizeof(struct y));
return mystruct;
void mystruct_free(struct mystruct *mystruct)
for (int i = 0; i < mystruct->list_length; i++)
free(mystruct->list[i]);
free(mystruct->list);
free(mystruct);
int main(int argc, char *argv[])
struct mystruct *h1 = mystruct_init();
h1->x = 6;
printf("%d\n", h1->x);
mystruct_free(h1);
return 0;
【讨论】:
如何引用 y ?我想你犯了一个错误:) 只是添加到@DanFego的代码中,完成后一定要free()
从malloc()
获得的内存。 Stack Overflow 上有很多线程解释了由于从函数返回局部变量而导致的内存泄漏。一个链接:***.com/a/423206/630866
@DanFego:我根据你的建议修改了程序。但是,当执行到达这一行时,我遇到了分段错误“mystruct->list[i] = calloc(1, sizeof(*(mystruct->list[i]));”出了什么问题?我应该粘贴我的完整代码?
@hektor 我的sizeof
可能有误。尝试将其更改为sizeof(struct y)
并查看它是否有效。 :)
@hektor 我只是快速地模拟了一个没有错误的程序,尽管我修复了上面的几个错别字,包括提到的那一行。也许你在错误的地方用括号更正了?【参考方案2】:
如果您只打算移植到支持 C99 的机器(编译器),那么您可以考虑使用“灵活数组成员”,它是“struct hack”的可移植版本。
§6.7.2.1 结构和联合说明符
¶16 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能 数组类型不完整;这称为灵活数组成员。有两个 例外,灵活的数组成员被忽略。首先,结构的尺寸应为 等于替换的相同结构的最后一个元素的偏移量 具有未指定长度的数组的灵活数组成员。106) 其次,当
.
(或->
) 运算符的左操作数是(指向)具有灵活数组成员的结构 并且正确的操作数命名该成员,它的行为就像该成员被替换 具有不会构成结构的最长数组(具有相同元素类型) 大于被访问的对象;数组的偏移量应保持在 灵活的数组成员,即使这与替换数组的不同。如果这 数组将没有元素,它的行为就像它只有一个元素,但行为是 如果尝试访问该元素或在过去生成一个指针,则未定义 它。¶17 示例假设所有数组成员在声明之后对齐相同:
struct s int n; double d[]; ; struct ss int n; double d[1]; ;
三种表达方式:
sizeof (struct s) offsetof(struct s, d) offsetof(struct ss, d)
具有相同的值。结构体struct
s
有一个灵活的数组成员d
。106) 未指定长度以允许实现可能给数组成员不同的事实 根据长度对齐。
在上下文中,这意味着你可以写:
typedef struct mystruct
int x;
struct y *list[];
mystruct; // Note that this is necessary; C++ automatically recognizes mystruct; C does not.
要分配空间,您可以使用:
mystruct *h1 = (mystruct *)malloc(sizeof(mystruct) + 10 * sizeof(struct y *));
这会分配一个mystruct
,并为数组中的 10 个指针分配足够的空间。您可以稍后调整内存大小:
mystruct *new_h1 = (mystruct *)realloc(h1, sizeof(mystruct) + 20 * sizeof(struct y *));
if (new_h1 == 0)
...handle out of memory error, but note that h1 is still valid...
h1 = new_h1; // Safe
(请注意,我在重新分配时小心不要分配给h1
;如果您遇到内存分配失败,这样做会泄漏内存。)
您可以像数组一样引用它们:
h1->list[0] = ...;
请注意,您不能拥有mystruct
的数组,但可以拥有指向mystruct
的指针数组。您还可以密切关注数组的大小;你通常会做一些事情,比如让一个固定成员记录分配的大小。
【讨论】:
以上是关于如何使用 malloc 动态声明结构中存在的数组的主要内容,如果未能解决你的问题,请参考以下文章
将字符分配给在 C 中使用 malloc 声明的二维数组时收到警告