If you want to make a copy of an array inside a function so that you can work on the array copy without changing the original array, the best option is to make an explicit copy of the array yourself.
The most portable way to do this is by using malloc()
or calloc()
to allocate memory, and then copying the contents of the original array to the new memory allocation. If you choose this path your code must be sure to free any dynamically allocated memory when it is no longer needed. The copying can be done by looping and using array index notation to access the allocated memory, or by using memcopy()
to copy the contents of the original array. Another option is to use a Variable Length Array (added to C with C99, made optional in C11 and C17 but still widely supported) to avoid dynamically allocating and deallocating the memory yourself.
Here is an example program that contains two functions, work_on_copy()
and work_on_copy_vla()
, that each take an array, copy it, and do some work that changes the copy. A final argument provides an array index which is used to illustrate how the array copy can be used to modify the original array selectively after work has been done inside the function. If this argument is a valid array index, the value at that index is copied from the array copy to the original array.
Note that this problem could also be solved by wrapping an array in a struct
, but this method has the disadvantage of requiring that the array member of that struct
be the same size as the largest array that is expected, wasting memory in the general case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(size_t arr_sz, int arr[]);
void work_on_copy(size_t arr_sz, int arr[], int index);
void work_on_copy_vla(size_t arr_sz, int arr[], int index);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4 };
size_t my_arr_sz = sizeof my_arr / sizeof *my_arr;
puts("-- Do not change original array at all --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
putchar('\n');
puts("-- Change specified index of original array after work --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, 1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, 3);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
return 0;
}
void print_array(size_t arr_sz, int arr[])
{
for (size_t i = 0; i < arr_sz; i++) {
printf("%d ", arr[i]);
}
putchar('\n');
}
void work_on_copy(size_t arr_sz, int arr[], int index)
{
/* make copy of array: could return a pointer to this allocation */
int *arr_copy = malloc(sizeof *arr_copy * arr_sz);
/* handle error if allocation fails */
if (arr_copy == NULL) {
perror("unable to allocate memory");
return;
}
memcpy(arr_copy, arr, sizeof *arr_copy * arr_sz); // or use a loop
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] += 10;
}
printf("Array copy after work (malloc): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
/* deallocate memory to avoid memory leaks */
free(arr_copy);
}
void work_on_copy_vla(size_t arr_sz, int arr[arr_sz], int index)
{
/* make local copy of array using a VLA */
int arr_copy[arr_sz];
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] = arr[i];
}
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] *= 2;
}
printf("Array copy after work (VLA): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
}
Program output:
-- Do not change original array at all --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 2 3 4
Array copy after work (VLA): 2 4 6 8
Array in main(): 1 2 3 4
-- Change specified index of original array after work --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 12 3 4
Array copy after work (VLA): 2 24 6 8
Array in main(): 1 12 3 8