Search code examples
carraysfunctionpass-by-value

Pass an array by value


Generally when we pass array by its name, it’s call by address. That means if we change any value of array outside main() it will be reflected in main().

So, what should I do to if I want to pass the array as an argument of a function and call it inside main() such that any change in that function won't be reflected inside main()?

For example:

void Foo(int arr[])   //takes an integer array `arr` as argument
{
    // do something with `arr
}

int main()
{
    int abc[]={5,1,2,9};
    //do something to pass `abc` inside `Foo` so that changes inside `Foo` doesn't change the value of `abc` array.
}

Now I want to pass the abc array to Foo by value.


Solution

  • It is possible to do this by wrapping the array in a struct. You can include a field for the size of the array so that you don't need to pass this parameter explicitly. This approach has the virtue of avoiding extra memory allocations that must later be freed.

    C already passes arguments to functions by value, but array identifiers decay to pointers in most expressions, and in function calls in particular. Yet structs do not decay to pointers, and are passed by value to a function, meaning that a copy of the original structure and all of its contents is visible in the scope of the function. If the struct contains an array, this is copied too. Note that if instead the struct contains, say, a pointer to int for a dynamic array, then the pointer is copied when the struct is passed to the function, but the same memory is referenced by both the copy and the original pointer. This approach relies on the struct containing an actual array.

    Also note that a struct can not contain a member with an incomplete type, and so can not contain a VLA. Here I have defined the global constant MAX_ARR to be 100 to provide some space for handling differently sized arrays with the same struct type.

    You can also return a struct from a function. I have included an example which modifies the Array struct which is passed into a function, and returns the modified struct to be assigned to a different Array struct in the calling function. This results in the caller having access to both the original and the transformed arrays.

    #include <stdio.h>
    
    #define MAX_ARR  100
    
    struct Array {
        size_t size;
        int array[MAX_ARR];
    };
    
    void print_array(struct Array local_arr);
    void func(struct Array local_arr);
    struct Array triple(struct Array local_arr);
    
    int main(void)
    {
        struct Array data = {
            .size = 10,
            .array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
        };
        struct Array transformed_data;
    
        func(data);
        transformed_data = triple(data);
    
        printf("Original\n");
        print_array(data);
    
        printf("Transformed\n");
        print_array(transformed_data);
    
        return 0;
    }
    
    void print_array(struct Array local_arr)
    {
        for (size_t i = 0; i < local_arr.size; i++) {
            printf("%5d", local_arr.array[i]);
        }
        putchar('\n');
    }
    
    void func(struct Array local_arr)
    {
        for (size_t i = 0; i < local_arr.size; i++) {
            local_arr.array[i] *= 2;
        }
        printf("Modified\n");
        print_array(local_arr);
    }
    
    struct Array triple(struct Array local_arr)
    {
        for (size_t i = 0; i < local_arr.size; i++) {
            local_arr.array[i] *= 3;
        }
        return local_arr;
    }
    

    Program output:

    Modified
        2    4    6    8   10   12   14   16   18   20
    Original
        1    2    3    4    5    6    7    8    9   10
    Transformed
        3    6    9   12   15   18   21   24   27   30