我应该如何malloc / realloc与包含数组的结构?

我对c很新,所以如果我的步骤有误,请告诉我。 假设我有以下内容:

struct graphNode{ int val; graphNode* parent; int succSize; int succMaxSize; graphNode* succ[1]; }; 

我将创建一个新节点:

 graphNode *n; n = malloc(sizeof(struct graphNode)); assert(n); n->val = 1; n->parent = NULL; n->succSize = 0; n->succMaxSize = 1; 

然后,如果我想向节点添加后继

 if (n->succSize == n->succMaxSize){ n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2); n->succMaxSize *= 2; } n->succ[succSize] = n2; //n2 is of type graphNode* succSize++; 

它是否正确? 我是否还需要为结构重新分配或者是否足够重新分配数组? 我需要malloc作为初始数组吗? 初始数组大小是否应包含在我的malloc调用n中?

在C中定义“弹性”数组成员的常用方法是指定大小为0或根本没有大小,例如:

 struct foo { int stuff; bar theBars[]; // or theBars[0] }; 

使用此定义, sizeof(struct foo)将包括末尾数组以外的所有元素,并且您可以通过说malloc(sizeof(struct foo) + numberOfBars * sizeof(bar))来分配正确的大小。

如果您需要重新分配它以更改bar元素的数量,那么您将使用相同的公式(但使用新的numberOfBars )。

要清楚,您不能只重新realloc结构的一部分。 你必须重新分配整个事情。

realloc(ptr,size)需要2个参数,而不是realloc(sizeof(graphNode*) * n->succMaxSize * 2)使用的1个参数realloc(sizeof(graphNode*) * n->succMaxSize * 2)

 // Something like ... graphNode *n; n->succSize = 0; n->succMaxSize = 0; // set to 0 n->succ = NULL; // Initialize to NULL // Then, if OP wants to add a successor to the node if (n->succSize <= n->succMaxSize){ n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2); n->succMaxSize *= 2; } n->succ[succSize++] = n2; 

与所有内存分配一样,检查NULL返回。 在realloc() ,应该保存原始值,因此如果realloc()失败,原始指针不会丢失。

通常,当您看到struct definition时,最后一个字段是一个大小为0或1的数组,这意味着当结构被malloced时,作者将使用malloc做一些微妙的事情。

例如

 struct foo { int x; : : type a[0]; }; 

有了malloc之类的

  struct foo *p = malloc(sizeof(*p) + (n * sizeof(type)); 

这样做是为结构和尾随数组分配一块连续的内存。 在这种情况下,数组大小为n。 因此,在这种情况下对数组的引用是:

 p->a[i] // where i >= 0 and i < n 

这样做的一个原因是节省内存。

我确信在StackOver上有更好的解释; 这是一个非常常见的C语言。

当arrays是动态的时,通常不使用它。 而是在malloc()时知道数组大小时使用它。 当然,您可以动态使用,但必须重新分配整个内存块,而不仅仅是结构或数组。 你会说,要将大小增加到2n

  p = realloc(p, sizeof(*p) + (2 * n * sizeof(type))); 

现在你的数组是两倍大,它仍然是一块内存。

如果你只想要一个数组,只需要succ一个指针,只使用malloc / realloc等来为数组分配内存。

 graphNode* succ; 

你在做什么几乎肯定会打破。

我也是C的新手,但有些东西我可以直接看到。 首先,您无法重新分配数组。 在c89中,它们是编译时固定大小的。 在C99和C11中,它们可以动态分配,但不能重新分配(据我所知)。 所以为此,你需要分配一个

 graphnode *succ; 

指针和malloc(节点* sizeof(节点))。

 graphNode* succ[1]; 

这将创建一个大小为1的数组,而不是最大索引为1的数组。 因此,它与function相同(几乎)

 graphNode* succ; 

除了你做完之后你不能改变它的大小。

我认为你想要的是制作一棵树,具有动态可重新分配的分支数量。 在这种情况下,您只需要重新分配graphNode *指针的大小,然后通过索引访问每个元素,就像访问数组一样。