-
C - Reallocating memory for the array
I just started delving into C and I had some issues with increasing the memory allocation size for my array. The best way to understand something - write a detailed explanation of the process. So here we go:
#include <stdio.h> #include <stdlib.h> // notice that array is a pointer to a pointer int append_array_element(int **array, int *array_length, int element) { *array_length += 1; *array = realloc(*array, *array_length * sizeof(int)); (*array)[*array_length - 1] = element; // [] has higher priority // then * in C's order of return 0; // operations }
We have a pointer to the pointer to the array, pointer to the arrayâs length, and a value to append to the array. Array is passed as a pointer to pointer so we will be able to ârepointâ the original pointer to a new memory segment.
Letâs call the function a few times and see what it gives us.
int main() { int *array = NULL; int array_length = 0; append_array_element(&array, &array_length, 142); printf ("Our array with %d elementsn", array_length); printf("%dn", array[0]); append_array_element(&array, &array_length, 19); printf ("Our array with %d elementsn", array_length); printf("%dn", array[0]); printf("%dn", array[1]); return 0; }
And the output is:
Our array with 1 elements 142 Our array with 2 elements 142 19
You can never be sure when you work with memory, so letâs add some error handling in case the operation fails.
int append_array_element(int **array, int *array_length, int element) { *array_length += 1; // realloc() returns pointer or False if it fails void *_tmp_array = realloc(*array, *array_length * sizeof(int)); if (!_tmp_array) { printf("Error while trying to realloc memory!n"); return -1; } *array = _tmp_array; (*array)[*array_length - 1] = element; return 0; }
Now we will be able to handle the crash on our own. But reallocation is not a very fast thing, so letâs double the amount of reallocated memory every time we run out of allocated memory. Weâll need one more variable to track the current allocated memory size.
int append_array_element(int **array, int *array_length, int *array_alloc_length, int element) { *array_length += 1; if (*array_length > *array_alloc_length) { if (*array_alloc_length == 0) { *array_alloc_length = 1; } else { *array_alloc_length *= 2; } void *_tmp_array = realloc(*array, *array_alloc_length * sizeof(int)); if (!_tmp_array) { printf("Error while trying to reallocate memory for an array!n"); return -1; } *array = _tmp_array; } (*array)[*array_length - 1] = element; return 0; }
Letâs call it few times:
int main() { int *array = NULL; int array_length = 0; int array_alloc_length = 0; int i; for (i = 0; i < 10; i++) { append_array_element(&array, &array_length, &array_alloc_length, i); } printf("Our array with %d elementsn", array_length); for (i = 0; i < 10; i++) { printf("%dn", array[i]); } printf("Array length: %d, allocated elements: %dn", array_length, array_alloc_length); return 0; } Our array with 10 elements 0 1 2 3 4 5 6 7 8 9 Array length: 10, allocated elements: 16
And for the fun of it, letâs do the same with 100 elements:
Our array with 100 elements 0 1 2 ... 97 98 99 Array length: 100, allocated elements: 128
Letâs improve the function a little bit more - and we are good to go. Letâs say we have a dynamic array with 129 elements - but we will have allocated memory for 256 elements⌠It is 127 more then we need! We donât want to be greedy, so letâs find a way to free up the memory.
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> // I included this just to use boolean values with // neat true/false aliases int append_array_element(int **array, int *array_length, int *array_alloc_length, int element, bool is_last_element) { *array_length += 1; if (*array_length > *array_alloc_length || is_last_element) { if (is_last_element) { *array_alloc_length = *array_length; } else if (*array_alloc_length == 0) { *array_alloc_length = 1; } else { *array_alloc_length *= 2; } void *_tmp_array = realloc(*array, *array_alloc_length * sizeof(int)); if (!_tmp_array) { printf("Error while trying to reallocate memory for an array!n"); return -1; } *array = _tmp_array; } (*array)[*array_length - 1] = element; return 0; }
That should be pretty straight-forward. And letâs call it two more times with 10 and 100 elements:
int main() { int *array = NULL; int array_length = 0; int array_alloc_length = 0; bool is_last_element; int i; int i_max = 10; for (i = 0; i < i_max; i++) { if (i == i_max - 1) { is_last_element = true; } else { is_last_element = false; } append_array_element(&array, &array_length, &array_alloc_length, i, is_last_element); } printf("Our array with %d elementsn", array_length); for (i = 0; i < i_max; i++) { printf("%dn", array[i]); } printf("Array length: %d, allocated elements: %dn", array_length, array_alloc_length); return 0; }
And the results are:
Our array with 10 elements 0 1 2 3 4 5 6 7 8 9 Array length: 10, allocated elements: 10 Our array with 100 elements 0 1 2 ... 97 98 99 Array length: 100, allocated elements: 100
Pretty neat, huh? Thank you for reading!