0

When using nested structures I tend to do something like the following. I would like to know if that's the proper way to initialize structs in this particular case or if there's a better way of doing it.

#include <string.h>
#include <stdlib.h>

typedef struct inner_struct { 
   char *name;
   int account;
} inner;

typedef struct outer_struct {
   int count;
   char *company; 
   inner *my_inner;
} outer;

outer *
initialize_outer (size_t max) {
   outer *out = malloc(sizeof (outer) * max);
   if (out) {
      memset(out, 0, sizeof *out * max);
      out->count = 0;
      out->company = NULL; 
   }   
   return out;
}

inner *
initialize_inner () {
   inner *in = malloc(sizeof (inner));
   if (in) {
      memset(in, 0, sizeof *in);
      in->account = 0;
      in->name = NULL; 
   }   
   return in; 
}

int main(int argc, char *argv[]){
   int i;
   size_t max_out = 20;
   outer *my_out = initialize_outer(max_out);
   for (i = 0; i<max_out;i++) {
      my_out[i].my_inner = initialize_inner();
   }
}
4
  • 1
    Why do you assign 0 to variables after a memset? Commented Dec 14, 2012 at 5:10
  • @Nick: that's exactly the part I wasn't sure of. Apparently is not needed. Commented Dec 14, 2012 at 5:21
  • It is not needed: a bigger problem is that you allocate a bunch of outers and then allocate a bunch of inners but assign them just to the first outer. Commented Dec 14, 2012 at 5:25
  • I meant to do my_out[i].my_inner. Thanks for the heads up! Commented Dec 14, 2012 at 5:39

3 Answers 3

4

Why not use calloc():

outer *
initialize_outer (size_t max) {
    return calloc(max, sizeof(outer));
}

inner *
initialize_inner (size_t max) {
    return calloc(max, sizeof(inner));
}

However, I would probably do this for simplicity:

typedef struct outer_struct {
    int count;
    char *company; 
    inner my_inner[];
} outer;

outer *
initialize (size_t max_out, size_t max_in) {
    return calloc(1, (sizeof (outer) + sizeof (inner) * max_in) * max_out);
}

int main(int argc, char *argv[]){
    size_t max_out = 20, max_in = 10; 
    outer *my_out = initialize(max_out, max_in);
    ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is a nice approach too. Thanks!
1
outer *
initialize_outer (size_t max) {
    outer *out = malloc(sizeof (outer) * max);
    if (out) {
        memset(out, 0, sizeof (outer) * max);
        out->count = 0; // no need assign 0 to 'account' and NULL to 'name' field
        out->company = NULL; // because memset already assigns 0 to it.
    }   
    return out;
}

inner *
initialize_inner (size_t max) {
    inner *in = malloc(sizeof (inner) * max);
    if (in) {
        memset(in, 0, sizeof (inner) * max);
        in->account = 0; // no need assign 0 to 'account' and NULL to 'name' field
        in->name = NULL; // because memset already assigns 0 to it.
    }   
    return in; 
}

Try this...I hope this helps...

2 Comments

so basically memset would init the struct fields to 0 regardless their type, is that correct?
is the above solution(CODE) helpful
1

Apart from the superfluous assignments to zero, you should probably call initialize_inner from initialize_outer, since it doesn't seem like "outer" fills any purpose without "inner.

This brings up another issue: you should consider using proper, object-oriented program design, with private encapsulation.

inner.h

typedef struct inner_struct;


inner* inner_init (void);
void   inner_free (inner* in); // you need a cleanup function!

// an example of a "setter" function:
void init_set_name (inner* in, const char* name);  

// similar setter and getter functions needed here

inner.c

#include "inner.h"

typedef struct { 
   char* name;
   int   account;
} inner;

inner* inner_init (void) 
{
   inner* in = calloc(1, sizeof (inner));
   if (in == NULL)
   {
     // error_handling
   }

   return in; 
}

void inner_free (inner* in)
{
  // if in->name was allocated dynamically, free it here

  free(in);
}

void init_set_name (inner* in, const char* name)
{
  // assign name to in->name, possibly malloc memory for it
}

outer.h

#include "inner.h"

typedef struct outer_struct;


outer* outer_init (void);
void   outer_free (outer* out);

// setter and getter functions needed here

outer.c

#include "outer.h"

typedef struct 
{
   int count;
   char *company; 
   inner *my_inner;
} outer;


outer* outer_init (void) 
{
   outer* out = calloc(1, sizeof(outer));
   if(out == NULL)
   {
     // error handling
   }

   out->my_inner = inner_init();

   return out;
}

void outer_free (outer* out)
{
  inner_free(out->my_inner);
  free(out);
}

the_application.c

#include "outer.h"

#define MAX_OUT 20

int main(int argc, char *argv[]){

   outer* out_arr [MAX_OUT]

   for(int i=0; i<MAX_OUT; i++)
   {
     out_arr[i] = outer_init();
   }

   ...

   for(int i=0; i<MAX_OUT; i++)
   {
     outer_free(out_arr[i]);
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.