简体   繁体   English

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

[英]How should I malloc/realloc with a struct that includes an array?

I'm pretty new to c, so if my steps are wrong, please let me know. 我对c很新,所以如果我的步骤有误,请告诉我。 Let's say that I have something like the following: 假设我有以下内容:

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

I will create a new node with: 我将创建一个新节点:

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

Then, if I want 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; //n2 is of type graphNode*
succSize++;

Is this correct? 这个对吗? Do I need to realloc for the struct as well or is realloc of the array enough? 我是否需要为结构重新分配或者是否足够重新分配数组? Do I need to malloc for the initial array? 我需要malloc作为初始数组吗? Should the initial array size be included in my malloc call for n? 初始数组大小是否应包含在我的malloc调用n中?

The usual way to define a "stretchy" array member in C is to either specify a size of 0 or no size at all, eg: 在C中定义“弹性”数组成员的常用方法是指定大小为0或根本没有大小,例如:

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

With this definition, sizeof(struct foo) will include all the elements other than the array at the end, and you can allocate the right size by saying malloc(sizeof(struct foo) + numberOfBars * sizeof(bar)) . 使用此定义, sizeof(struct foo)将包括末尾数组以外的所有元素,您可以通过说malloc(sizeof(struct foo) + numberOfBars * sizeof(bar))来分配正确的大小。

If you need to reallocate it to change the number of bar elements, then you'll use the same formula (but with a new numberOfBars ). 如果您需要重新分配它以更改bar元素的数量,那么您将使用相同的公式(但使用新的numberOfBars )。

To be clear, you can't just realloc part of a struct. 要清楚,你不能只重新realloc一个结构的一部分。 You have to realloc the whole thing. 你必须realloc整个事情。

realloc(ptr,size) needs 2 parameters, not 1 as used in realloc(sizeof(graphNode*) * n->succMaxSize * 2) 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;

As with all memory allocations, check for NULL return. 与所有内存分配一样,检查NULL返回。 In realloc() , one should save the original value, so if the realloc() fails, the original pointer is not lost. realloc() ,应该保存原始值,因此如果realloc()失败,原始指针不会丢失。

Usually when you see struct definition where the last field is an array of size 0 or 1 it means the author is going to do some subtle stuff with malloc when the struct is malloced. 通常当你看到结构定义,其中最后一个字段是一个大小为0或1的数组时,这意味着当结构被malloced时,作者将使用malloc做一些微妙的东西。

For example 例如

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

With a malloc like 有了malloc之类的

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

What this does is it allocates a contiguous chunk of memory for the struct and the trailing array. 这样做是为结构和尾随数组分配一块连续的内存。 In this case the array size is n. 在这种情况下,数组大小为n。 So references to the array in this case are: 因此,在这种情况下对数组的引用是:

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

One reason for doing this is to save memory. 这样做的一个原因是节省内存。

I'm sure there are better explanations for this on StackOver; 我确信在StackOver上有更好的解释; it's a very common C idiom. 这是一个非常常见的C语言。

It's generally not used when the array is dynamic. 当阵列是动态的时,通常不使用它。 Rather, it is used when the array size is known at malloc() time. 而是在malloc()时知道数组大小时使用它。 You can use dynamically, of course, but you have to realloc the entire memory chunk, not just the struct or array by itself. 当然,您可以动态使用,但必须重新分配整个内存块,而不仅仅是结构或数组。 To increase the size to 2n you would say 你会说,要将大小增加到2n

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

Now your array is twice is big as it was, and it's still one chunk of memory. 现在你的数组是两倍大,它仍然是一块内存。

If you only want a single array, just make succ a single pointer and only use malloc/realloc etc. to allocate memory for the array. 如果你只想要一个数组,只需要succ一个指针,只使用malloc / realloc等为数组分配内存。

graphNode* succ;

What you are doing is almost certain to break. 你在做什么几乎肯定会打破。

I too am new to C, but there's some things that I can see right off the bat. 我也是C的新手,但有些东西我可以直接看到。 First of all, you can't re-allocate arrays. 首先,您无法重新分配数组。 In c89, they're compile-time fixed-size. 在c89中,它们是编译时固定大小的。 In C99 and C11, they can be dynamically allocated, but not reallocated (as far as I'm aware). 在C99和C11中,它们可以动态分配,但不能重新分配(据我所知)。 So for this, you need to allocate a 所以为此,你需要分配一个

graphnode *succ; 

pointer, and malloc(nodes * sizeof(node)). 指针和malloc(nodes * sizeof(node))。

graphNode* succ[1];

This creates an array of size one, not an array with a maximum index of one. 这将创建一个大小为1的数组,而不是最大索引为1的数组。 So, it is the same (almost) functionally as 因此,它与功能相同(几乎)

graphNode* succ;

except that you can't change its size once you've made it. 除了你做完之后你不能改变它的大小。

I think what you want is to make a tree, with a dynamically re-allocable amount of branches. 我认为你想要的是制作一棵树,具有动态可重新分配的分支数量。 In this case, you only need to reallocate the size of the graphNode* pointer, and then access each element via index as you would an array. 在这种情况下,您只需要重新分配graphNode *指针的大小,然后像索引一样通过索引访问每个元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM