[ACCEPTED]-Passing a dynamic array in to functions in C-realloc
The main problem here is that you're trying 24 to use realloc with a stack-allocated array. You 23 have:
ent a[mSize];
That's automatic allocation on the 22 stack. If you wanted to use realloc() on 21 this later, you would create the array on 20 the heap using malloc(), like this:
ent *a = (ent*)malloc(mSize * sizeof(ent));
So that 19 the malloc library (and thus realloc(), etc.) knows 18 about your array. From the looks of this, you 17 may be confusing C99 variable-length arrays with true dynamic arrays, so be sure 16 you understand the difference there before 15 trying to fix this.
Really, though, if you 14 are writing dynamic arrays in C, you should 13 try to use OOP-ish design to encapsulate 12 information about your arrays and hide it 11 from the user. You want to consolidate 10 information (e.g. pointer and size) about 9 your array into a struct and operations 8 (e.g. allocation, adding elements, removing 7 elements, freeing, etc.) into special functions 6 that work with your struct. So you might 5 have:
typedef struct dynarray {
elt *data;
int size;
} dynarray;
And you might define some functions 4 to work with dynarrays:
// malloc a dynarray and its data and returns a pointer to the dynarray
dynarray *dynarray_create();
// add an element to dynarray and adjust its size if necessary
void dynarray_add_elt(dynarray *arr, elt value);
// return a particular element in the dynarray
elt dynarray_get_elt(dynarray *arr, int index);
// free the dynarray and its data.
void dynarray_free(dynarray *arr);
This way the user 3 doesn't have to remember exactly how to 2 allocate things or what size the array is 1 currently. Hope that gets you started.
Try reworking it so a pointer to a pointer 3 to the array is passed in, i.e. ent **a
. Then you 2 will be able to update the caller on the 1 new location of the array.
You are passing the array pointer by value. What 9 this means is:
int main(int argc, char** argv) {
...
ent *a; // This...
...
}
int addValues(ent *a, int mSize) {
...
a = calloc(1, sizeof(ent); // ...is not the same as this
//usual loop
...
}
so changing the value of a 8 in the addValues
function does not change the value 7 of a in main. To change the value of a in 6 main you need to pass a reference to it 5 to addValues
. At the moment, the value of a is being 4 copied and passed to addValues
. To pass a reference 3 to a use:
int addValues (int **a, int mSize)
and call it like:
int main(int argc, char** argv) {
...
ent *a; // This...
...
addValues (&a, mSize);
}
In the addValues
, access 2 the elements of a like this:
(*a)[element]
and reallocate 1 the array like this:
(*a) = calloc (...);
this is a nice reason to use OOP. yes, you 4 can do OOP on C, and it even looks nice 3 if done correctly.
in this simple case you 2 don't need inheritance nor polymorphism, just 1 the encapsulation and methods concepts:
- define a structure with a length and a data pointer. maybe an element size.
- write getter/setter functions that operate on pointers to that struct.
- the 'grow' function modifies the data pointer within the struct, but any struct pointer stays valid.
If you changed the variable declaration 12 in main to be
ent *a = NULL;
the code would work more like 11 you envisioned by not freeing a stack-allocated 10 array. Setting a to NULL works because realloc 9 treats this as if the user called malloc(size). Keep 8 in mind that with this change, the prototype 7 to addValue needs to change to
int addValues(ent **a, int mSize)
and that the 6 code needs to handle the case of realloc 5 failing. For example
while(....) { //Loop to add items to array
tmp = realloc(*a, size*sizeof(ent));
if (tmp) {
*a = tmp;
} else {
// allocation failed. either free *a or keep *a and
// return an error
}
//Add to array
i++;
}
I would expect that 4 most implementations of realloc will internally 3 allocate twice as much memory if the current 2 buffer needs resizing making the original 1 code's
size = size * 2;
unnecessary.
Xahtep explains how your caller can deal 7 with the fact that realloc() might move 6 the array to a new location. As long as 5 you do this, you should be fine.
realloc() might 4 get expensive if you start working with 3 large arrays. That's when it's time to start 2 thinking of using other data structures 1 -- a linked list, a binary tree, etc.
As stated you should pass pointer to pointer 8 to update the pointer value.
But I would 7 suggest redesign and avoid this technique, in 6 most cases it can and should be avoided. Without 5 knowing what exactly you trying to achieve 4 it's hard to suggest alternative design, but 3 I'm 99% sure that it's doable other way. And 2 as Javier sad - think object oriented and you 1 will always get better code.
Are you really required to use C? This 4 would be a great application of C++'s "std::vector", which 3 is precisely a dynamically-sized array (easily 2 resizeble with a single call you don't have 1 to write and debug yourself).
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.