【问题标题】:How to dynamically declare a array present inside a structure using malloc如何使用 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

标签: c arrays struct


【解决方案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 上有很多线程解释了由于从函数返回局部变量而导致的内存泄漏。一个链接:stackoverflow.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 的指针数组。您还可以密切关注数组的大小;你通常会做一些事情,比如让一个固定成员记录分配的大小。

【讨论】:

    猜你喜欢
    • 2020-11-09
    • 2017-02-11
    • 2017-05-29
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多