3

I currently have no code, because I don't know how to do this at all. Could I just, by myself, calculate how many bytes is needed for each lower-level struct and malloc it to it? That's really terrible coding, isn't it. Here's the two structs I'm trying to mash together:

struct property {
    int d;
    char name [111]; // I just malloc this like I would a normal array, right?
    char descr [1025]; // Ditto.
}

struct category {
    int d [413]; // The d's of all the child structs sorted highest to lowest.
    char name [111];
    struct property property [413]; // This. How do I allocate this?
}</code>

Do I have to do struct property* property = (struct property*) malloc(sizeof(struct property) * 413);? Will the malloc of the array within remain intact? How do mallocs in structs behave in general?

mszegedy
  • 185
  • 1
  • 9
  • "Do I have to do struct property* property = (struct property*) malloc(sizeof(struct property) * 413);?" <-- certainly not in this form, as you're casting the return value of malloc(). Don't do that. –  May 27 '12 at 07:16

3 Answers3

4

You don't have a pointer member inside your structure property so you don't need to malloc any of your structure members.
When you malloc for the structure it will give you enough memory to hold all the structure members including arrays, exceptions are pointer structure members(You don't have any).

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • But I will, once I malloc property.name and property.descr, won't I? What happens then? – mszegedy May 27 '12 at 18:26
  • @mszegedy: You don't need to `malloc`, `property.name` and `property.descr`, they are Arrays not pointers, Only pointer structure members need memory allocation. – Alok Save May 28 '12 at 02:40
3

Your malloc without the cast would do fine. It allocates contiguous memory for the whole array. The arrays inside the struct's are all allocated along with it, they are proper arrays and not pointers.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
2

Sizeof will give you the size of your entire structure. It properly accounts for the size of arrays and structures.

However, 413 items seems arbitrary. Would a variable sized structure work better for you?

In that case, calculating the size ahead of time to avoid mallocs is a good performance idea. Malloc can be slow, it can require locks, and the heap can fragment over time. This example shows you how to make a "variable length" structure with a pointer instead of an array or a variable length array at the end of your structure:

struct category
{
  int              cItems;  // need this if handling variable # of items now.
  int             *d;  // ptr instead of array
  char            *name;  // ptr again
  struct property  property[0];  // var length array
}


int cItems = 413; // or whatever
// this is a nifty trick to get the size of a variable length struct:
int cbCategory = (size_t)(&((struct category*)0)->property[cItems]);
int cbD = sizeof(int)*cItems;
int cbName = sizeof(char)*cItems;
struct category *pCategory  = (struct category*)malloc(cbCategory + cbD + cbName);
// wire up d:
pCategory->d = (int*)((char*)pCategory + cbCategory);
// or wire d up this way:
pCategory->d = (int*)&pCategory->property[cItems];
// wire up name
pCategory->name = (char*)pCategory->d + cbD;
// or wire up name this way
pCategory->name = (char*)&pCategory->d[cItems];
// set items
pCategory->cItems = cItems;

Note, I assumed that d had 413 elements to it. I could have just as easily left it a an array.

johnnycrash
  • 5,184
  • 5
  • 34
  • 58