When is it better to instantiate a variable length array with calloc vs. "normal" array declaration in C?
Consider the 'array declaration' approach:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int n = atoi(argv[1]);
int x[n];
for(int i = 1; i < n; i ){
x[i] = i;
printf("%i", x[i]);
printf("\n");
}
return 0;
}
vs. the calloc approach:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int n = atoi(argv[1]);
int * x = (int*) calloc(n, sizeof(int));
for(int i = 1; i < n; i ){
x[i] = i;
printf("%i", x[i]);
printf("\n");
}
return 0;
}
Should you always use one or the other? Is one faster than the other (e.g. bc of stack vs heap allocation)? Is one a lot riskier than the other?
CodePudding user response:
int x[n];
Automatic storage duration objects including VLAs are (by most modern implementations) allocated on the stack. There are some problems with the larger objects if they are allocated on the stack (three most important ones):
- There is no allocation control unless your program fails when you overflow the stack
- Stack is usually much much smaller than the heap. So the size of the array is limited
- The lifetime of the array is limited to the lifetime of the enclosing block. You can't return the reference to this array on the function return.
CodePudding user response:
the huge difference is that in the first example the array only exist for the life of the containing function but in the second case it lives on until its released.
In your example there is only the main function so the difference doesnt matter, but in real applications it matters a lot.
Second there is a limit to how large the first one can be since its allocated on the stack which is a limited resource. (Try it, make the array 1 million elements). The second case is limited only by the size of the heap, which is usually much much larger
CodePudding user response:
Ask these two questions "Will my array size fit in the stack ?" and "for how long do i need this array (program or function life time)?".
Statically allocated arrays exist for the life time of the function. when return, the function stack (and any variables declared local to that function including your array) are destroyed, and any attempt to access them gives an undefined behavior.
However, if you do need to return a pointer to your array so that the values you store are available back in the calling function, then you do need to dynamically allocate it, When you dynamically allocate memory with calloc the lifetime extends from the time the memory is allocated, until it is deallocated.
Keep in mind that statically allocated memory are faster and more efficient than a dynamically allocated one so if you don't really need it don't be fancy.
CodePudding user response:
Variable length arrays is conditionally supported by implementation.
If there is defined the macro name __STDC_NO_VLA__ then integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.
Another problem is that the stack memory usually is much less than the memory used for dynamic memory allocation.
The size of a variable length array can be automatically changed then the control reaches anew the declaration of the array.
Variable length arrays have automatic storage duration and block scopes. So they are alive in block scopes where they are defined.
A dynamically allocated array can be resized using the function realloc preserving current values of its elements and you can explicitly control situations in the program when there is no enough space for a dynamically allocated array.
CodePudding user response:
Generally speaking, only truly safe use of variable length arrays is for local typedef of multi-dimensional arrays. Anything else is dubious. Something like:
void *buf = calloc(a*b, sizeof(int));
typedef int Int2d[a][b];
Int2D *array2d = buf;
(*array2d)[y][x] = 42;
So use the calloc version. Only if you have a known small size, use VLA directly. And yes, that is a bit of a contradiction.
