如何使用 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) 其次,当.(或-&gt;) 运算符的左操作数是(指向)具有灵活数组成员的结构 并且正确的操作数命名该成员,它的行为就像该成员被替换 具有不会构成结构的最长数组(具有相同元素类型) 大于被访问的对象;数组的偏移量应保持在 灵活的数组成员,即使这与替换数组的不同。如果这 数组将没有元素,它的行为就像它只有一个元素,但行为是 如果尝试访问该元素或在过去生成一个指针,则未定义 它。

¶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 声明的二维数组时收到警告

如何定义一个动态的数组

如果存在 VLA,为啥仍然需要 malloc? [复制]

如何为多维数组动态分配内存

如何将数据存储在动态二维数组中,该数组在 C++ 中的另一个结构中也使用的结构中声明

C语言里,啥时候用数组啥时候用指针和动态内存(malloc/calloc)?