简体   繁体   中英

Dynamic memory allocation for an array and an array of structures within a struct

I am a newbie in C..I am trying to make some sense of how dynamic memory allocation works in case of structures and arrays..So like for example I have a code like..

struct Person
{
    int id;
    char *name;
    char *place;
};

struct Database
{ 
    struct Person *data_rows;
};

I want to dynamically allocate memory for both the character arrays name and place..and the array of struct data_rows..take their size as input..So what should ideally be the order of allocations and the proper syntax for the same? Thanks.

Well, "obviously" you need to get "struct Database" filled in first:

struct Database MyDatabase;

MyDatabase.data_rows=malloc(sizeof(MyDatabase.data_rows[0])*NumberOfPeople);

Ignoring the fact that I didn't check the malloc() for failure, this will give you an array of "struct Person", all uninitialized. So, most likely, you'll want to initialize them:

int i;
for (i=0; i<NumberOfPeople; i++)
{
   struct Person* MyPerson;

   MyPerson=&MyDatabase.data_rows[i];
   MyPerson->id=i;
   MyPerson->name=malloc(...);
   /* Do something to store the name in MyPerson->name */
   MyPerson->place=malloc(...);
   /* Do something to store the place in MyPerson->name */
}

Now, the problem here is the "..." I put on the malloc. It's easy if you use a fixed size, but then you could have just declared your struct to be something like

struct Person
{
    int id;
    char name[100];
    char place[200];
};

Basically, I just can't tell what the length of the names should be, hence I just typed it as "...".

Also, I just guessed what the "id" might be. Using the array index is actually somewhat pointless :-)

Of course, you don't have to do it all now. You could just set the name and place pointers to NULL and fill them in later, like when you're reading the data from a file, or whatever you're planning to do. Or you could just not initialize it here at all, if you're confident that your code always "knows" which fields are initialized and which ones are not.

I would highly recommend to write a functions person_new and person_free that would take care of structure memory management:

struct Person* person_new(char *name, char* place) {
  struct Person* person = malloc(sizeof(struct Person));

  person->name = strdup(name);
  person->place = strdup(place);

  return person;
}

void person_free(struct Person* person) {
  free(person->name);
  free(person->place);
  free(person);
}

The best thing would be to convert your structs to classes, the following works also for structs...

You define a constructor and destructor in Database and in Person as following:

struct Person
{
    Person(){
        name = new char[256];
        place = new char[256]; 
    };
    ~Person(){
       delete name; 
       delete place;
    }

    int id;
    char *name;
    char *place;
};

struct Database
{ 
    Database(int nPersons){
       data_rows = new Person[nPersons]; 
    };
    ~Database(){
       delete data_rows;
    };
    struct Person *data_rows;
};

or you can do this without a constructor and destructor and allocate all the stuff sequentially in your code, which is a very ugly way to do this!

as:

Database myData;
myData.data_rows = new Persons[40];
for(int i=0; i < 40; i++){
   myData.data_rows[i].name = new char[256];
   myData.data_rows[i].place = new char[256];
}

Note that data_rows[i] is nothing more than -> *(data_rows + i) which shifts the address of the pointer i times and then dereferences it!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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