tags:

views:

207

answers:

4

I'm a bit new to malloc and C in general. I wanted to know how I can, if needed, extend the size of an otherwise fixed-size array with malloc.

Example:

#define SIZE 1000
struct mystruct
{
  int a;
  int b;
  char c;
};
mystruct myarray[ SIZE ];
int myarrayMaxSize = SIZE;
....
if ( i > myarrayMaxSize )
{
   // malloc another SIZE (1000) elements
   myarrayMaxSize += SIZE;
}
  • The above example should make clear what I want to accomplish.

(By the way: I need this for an interpreter I write: Work with a fixed amount of variables and in case more are needed, just allocate them dynamically)

+3  A: 

Use realloc, but you have to allocate the array with malloc first. You're allocating it on the stack in the above example.

   size_t myarray_size = 1000;
   mystruct* myarray = malloc(myarray_size * sizeof(mystruct));
   myarray_size += 1000;
   mystruct* myrealloced_array = realloc(myarray, myarray_size);
   if (myrealloced_array) {
     myarray = myrealloced_array;
   } else {
     // deal with realloc failing because memory could not be allocated.
   }
jeffamaphone
`x = realloc(x, newsize)` is a memory leak waiting to happen.
R Samuel Klatchko
Good point. I've updated the example code to handle realloc failures.
jeffamaphone
`myarray = myrealloced_array)` should be `myarray = myrealloced_array;` :)
Saul Rennison
Heh, excuse the typos. I'm responding from a mobile device in the middle of a meeting. :)
jeffamaphone
You don't necessarily have to allocate with `malloc()` first - "if ptr is a null pointer, the realloc function behaves like the malloc function for the specified size"
Michael Burr
@Michael Burr: However, if you do it with a stack-allocated pointer, things get more interesting. And by interesting I mean undefined.
Platinum Azure
@Platinum: it should go without saying that the pointer would have to be appropriately initialized to `0`. I'm also not saying that it makes sense to always avoid using `malloc()` for the initial allocation, but there are some scenarios where it might work nicely to drop right into the loop that does the realloc, even for the initial allocation.
Michael Burr
@Michael Burr: I think Platinum Azure meant a pointer to an object on the stack. And you wouldn't want to use it with a pointer to something that came from some other allocator. In other words, `realloc`'s input must be NULL or a pointer to a buffer previously allocated by `malloc`/`realloc`.
jamesdlin
@jamesdlin - to be insanely pedantic, the input to `realloc` can also come from `calloc`
R Samuel Klatchko
@Michael Burr: jamesdlin has it right. Now that I reread my comment that was horribly worded... I apologize. I do mean a pointer to something allocated on the stack. Of course, in many cases the pointer ITSELF is on the stack, even when it points to something in the heap. So sorry for that.
Platinum Azure
+4  A: 

No, you can't. You can't change the size of an array on the stack once it's defined: that's kind of what fixed-size means. Or a global array, either: it's not clear from your code sample where myarray is defined.

You could malloc a 1000-element array, and later resize it with realloc. This can return you a new array, containing a copy of the data from the old one, but with extra space at the end.

Steve Jessop
+1  A: 

a) you did not use malloc to create it so you cannot expand with malloc. Do:

  mystruct *myarray = (mystruct*)malloc(sizeof( mystruct) *SIZE);

b) use realloc (RTM) to make it bigger

pm100
+4  A: 

You want to use realloc (as other posters have already pointed out). But unfortunately, the other posters have not shown you how to correctly use it:

POINTER *tmp_ptr = realloc(orig_ptr, new_size);
if (tmp_ptr == NULL)
{
    // realloc failed, orig_ptr still valid so you can clean up
}
else
{
    // Only overwrite orig_ptr once you know the call was successful
    orig_ptr = tmp_ptr;
}

You need to use tmp_ptr so that if realloc fails, you don't lose the original pointer.

R Samuel Klatchko