Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I allocate more space for my array of C structs?

I'm trying to add 10 more elements to my struct that has been already malloc with a fixed sized of 20. This is the way I have my struct defined:

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

struct st_temp {
   char *prod;
};

int main ()
{
   struct st_temp **temp_struct;

   size_t j;
   temp_struct = malloc (sizeof *temp_struct * 20);
   for (j = 0; j < 20; j++) {
      temp_struct[j] = malloc (sizeof *temp_struct[j]);
      temp_struct[j]->prod = "foo";
   }

   return 0;
}

So what I had in mind was to realloc as (however, not sure how to):

temp_struct = (struct st_temp **) realloc (st_temp, 10 * sizeof(struct st_temp*));

and then add the extra 10 elements,

   for (j = 0; j < 10; j++)
      temp_struct[j]->prod = "some extra values";

How could I achieve this? Any help is appreciated!

like image 948
Josh Avatar asked Oct 31 '10 21:10

Josh


People also ask

How do you allocate memory for an array of structs?

The memory can be allocated using the malloc() function for an array of struct . This is called dynamic memory allocation. The malloc() (memory allocation) function is used to dynamically allocate a single block of memory with the specified size. This function returns a pointer of type void .

How do you allocate space for a struct?

To allocate a new person in the myperson argument, we use the following syntax: person * myperson = (person *) malloc(sizeof(person)); This tells the compiler that we want to dynamically allocate just enough to hold a person struct in memory and then return a pointer of type person to the newly allocated data.

How do I allocate more memory to C?

In C, dynamic memory is allocated from the heap using some standard library functions. The two key dynamic memory functions are malloc() and free(). The malloc() function takes a single parameter, which is the size of the requested memory area in bytes. It returns a pointer to the allocated memory.

How do you allocate space for an array of pointers?

Dynamically allocating an array of M pointers Dynamically allocating an array of pointers follows the same rule as arrays of any type: type *p; p = malloc(m* sizeof *p); In this case type is float * so the code is: float **p; p = malloc(m * sizeof *p);


2 Answers

When you use realloc(), you must give the new size instead of the number of bytes to add. So:

temp_struct = (struct st_temp **) realloc (temp_struct, 30 * sizeof(struct st_temp*));

30 is, of course, your original 20 plus 10 more. The realloc() function takes care of copying the original data to a new location if it needs to move the memory block.

Then, adding the extra 10 elements would be something like (starting at index 20, not 0):

for (j = 20; j < 30; j++) {
    temp_struct[j]->prod = "some extra values"; 
}
like image 157
Greg Hewgill Avatar answered Nov 08 '22 19:11

Greg Hewgill


To avoid memory leaks, we need to handle reallocating with care (more on that later). The realloc function:

void *realloc(void *ptr, size_t size), where

ptr = the pointer to the original (malloc'ed) memory block, and

size = the new size of the memory block (in bytes).

realloc returns the new location of the dynamically allocated memory block (which may have changed) - or NULL if the re-allocation failed! If it returns NULL, the original memory stays unchanged, so you must always use a temporary variable for the return value of realloc.

An example will clarify this a bit (points of interest: realloc syntax is similar to malloc's (no need for extra casts etc.) and, after realloc, you need to produce the same steps for the new objects as you did after malloc):

struct st_temp **temp_struct;
temp_struct = malloc(20 * sizeof *temp_struct);
if (temp_struct == NULL) { /* handle failed malloc */ }
for (int i = 0; i < 20; ++i) {
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "foo";
}

// We need more space ... remember to use a temporary variable
struct st_temp **tmp;
tmp = realloc(temp_struct, 30 * sizeof *temp_struct);
if (tmp == NULL) { 
    // handle failed realloc, temp_struct is unchanged
} else {
    // everything went ok, update the original pointer (temp_struct)
    temp_struct = tmp; 
}
for (int i = 20; i < 30; ++i) { // notice the indexing, [20..30)
    // NOTICE: the realloc allocated more space for pointers
    // we still need to allocate space for each new object
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "bar";
}
// temp_struct now "holds" 30 temp_struct objects
// ...
// and always do remember, in the end
for (int i = 0; i < 30; ++i)
    free(temp_struct[i]);
free(temp_struct);

Do note, that this is not really an array of structs, but more an array of pointers to structs - or even an array of arrays of struct if you wish. In the last case, each sub-array would be of length 1 (since we only allocate space for one struct).

like image 44
eq- Avatar answered Nov 08 '22 20:11

eq-