如何使用malloc动态声明结构中存在的数组

时间:2012-01-31 18:42:09

标签: c arrays struct

我目前在我的程序中有以下代码:

struct mystruct
{
    int x;
    struct y *list[10];
}

mystruct *h1=(mystruct *)malloc(sizeof(mystruct));

我想在声明结构时动态地声明数组list(使用malloc())。谁能告诉我怎么做呢?

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

如果您只是要移植到支持C99的机器(编译器),那么您可以考虑使用'灵活阵列成员',这是'struct hack'的可移植版本。

  

§6.7.2.1结构和联合说明符

     

¶16作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以   有一个不完整的数组类型;这称为灵活数组成员。有两个   异常,灵活的数组成员被忽略。首先,结构的大小应为   等于替换其他相同结构的最后一个元素的偏移量   具有未指定长度数组的灵活数组成员。 106)其次,.(或->时   operator有一个左操作数,它是一个带有灵活数组成员的结构(指向)   并且右边的操作数命名该成员,它的行为就像该成员被替换一样   最长的数组(具有相同的元素类型),不会构成结构   大于被访问的对象;数组的偏移量应保持为   灵活的阵列成员,即使这与替换阵列的成员不同。如果这   数组没有元素,它的行为好像它有一个元素,但行为是   如果尝试访问该元素或生成过去的指针,则为undefined   它

     

¶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 *));

这为数组中的10个指针分配了一个mystruct足够的空间。您可以稍后使用以下内容调整内存大小:

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的数组。您还需要密切关注阵列的大小;你通常会做一些固定成员记录分配大小的事情。