user13851309
user13851309

Reputation: 79

To pass an array by reference in C

I am trying to modify this merge sort codes from GeekstoGeeks with passing an array by reference.

/* C program for Merge Sort */
#include <stdio.h> 
#include <stdlib.h> 

// Merges two subarrays of arr[]. 
// First subarray is arr[l..m] 
// Second subarray is arr[m+1..r] 
void merge(int arr[], int l, int m, int r) 
{ 
    int i, j, k; 
    int n1 = m - l + 1; 
    int n2 = r - m; 

    /* create temp arrays */
    int L[n1], R[n2]; 

    /* Copy data to temp arrays L[] and R[] */
    for (i = 0; i < n1; i++) 
        L[i] = arr[l + i]; 
    for (j = 0; j < n2; j++) 
        R[j] = arr[m + 1 + j]; 

    /* Merge the temp arrays back into arr[l..r]*/
    i = 0; // Initial index of first subarray 
    j = 0; // Initial index of second subarray 
    k = l; // Initial index of merged subarray 
    while (i < n1 && j < n2) { 
        if (L[i] <= R[j]) { 
            arr[k] = L[i]; 
            i++; 
        } 
        else { 
            arr[k] = R[j]; 
            j++; 
        } 
        k++; 
    } 

    /* Copy the remaining elements of L[], if there 
    are any */
    while (i < n1) { 
        arr[k] = L[i]; 
        i++; 
        k++; 
    } 

    /* Copy the remaining elements of R[], if there 
    are any */
    while (j < n2) { 
        arr[k] = R[j]; 
        j++; 
        k++; 
    } 
} 

/* l is for left index and r is right index of the 
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r) 
{ 
    if (l < r) { 
        // Same as (l+r)/2, but avoids overflow for 
        // large l and h 
        int m = l + (r - l) / 2; 

        // Sort first and second halves 
        mergeSort(arr, l, m); 
        mergeSort(arr, m + 1, r); 

        merge(arr, l, m, r); 
    } 
} 

/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size) 
{ 
    int i; 
    for (i = 0; i < size; i++) 
        printf("%d ", A[i]); 
    printf("\n"); 
} 

/* Driver program to test above functions */
int main() 
{ 
    int arr[] = { 12, 11, 13, 5, 6, 7 }; 
    int arr_size = sizeof(arr) / sizeof(arr[0]); 

    printf("Given array is \n"); 
    printArray(arr, arr_size); 

    mergeSort(arr, 0, arr_size - 1); 

    printf("\nSorted array is \n"); 
    printArray(arr, arr_size); 
    return 0; 
} 

To something like this:

void mergeSort(int* arr[], int l, int r);
void merge(int* arr[], int l, int m, int r);

I thought it is a simple task because I could simply change every arr to *arr in the functions to dereference them. The program is still runnable but gives me a bunch of unknown numbers.

Then I searched the stack overflow until I see this post: https://stackoverflow.com/questions/49751409/swapping-2-arrays-in-c#:~:text=Since%20pointer%20is%2064%20bit,two%20int%20which%20get%20swapped.&text=In%20C%20an%20array%20is,they%20are%20pointers%20to%20arrays

It also passes an array by reference. (int* a and int* b)

void swapArray( int *a, int *b, size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        int tmp = a[i];
        a[i] = b[i];
        b[i] = tmp;
    }
}

But in reverse, when I change it to

void swapArray( int a, int b, size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        int tmp = a[i];
        a[i] = b[i];
        b[i] = tmp;
    }
}

It doesn't work, again. Could someone explain to me why and how can I modify my merge sort codes properly? Or where I should look for? I am so confused about this. Any help is appreciated.

Upvotes: 0

Views: 114

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409166

int *arr[] is an array of pointers. Or rather it's a pointer to a pointer (it's really int **arr).

To pass a pointer to an array (which almost never is needed) you need e.g. int (*arr) [6]. And yes, the size of the array is then mandatory (variable-length arrays are valid).

But as I said, passning pointers to arrays is almost never needed, because arrays naturally decays to pointers (to their first element).

And as an argument declaration int arr[] is equal to int *arr.

That is, with

void merge(int arr[], int l, int m, int r) 

you already pass the array by "reference".

Upvotes: 3

Eric Postpischil
Eric Postpischil

Reputation: 222372

The subscript operator, [ ], has higher precedence than the dereference operator, *. So int *arr[] declares arr to be an array of pointers to int. To make it a pointer to an array, you need int (*arr)[].

Similarly, in expressions, *arr[3] attempts to take element 3 of an array arr and dereference it. Instead you need (*arr)[3] to use *arr to get the array and then [3] to get element 3.

Upvotes: 1

Related Questions