0

I have passed a 2D array normally (by value) to a function "elem", which further passes it on to another function "interchange", which performs a row-interchange operation and displays it. But the problem is, after I return from interchange back to main(), the value of the array has been changed to the resultant array from interchange, even though technically they must be three different variables for three different functions (main, elem and interchange). Why is this so, and what can I do to make the array in main() remain unchanged?

//include files... 

void interchange(float c[10][10],int m,int n)
{
    int i,j,p,q;
    float temp;

        printf("\nEnter the two row numbers to interchange:");
        scanf("%d%d",&p,&q);

        if((--p<m)&&(--q<n))
        {
            for(i=0;i<m;i++)
            {
                temp=c[p][i];
                c[p][i]=c[q][i];
                c[q][i]=temp;
            }
        } else
        {
            printf("Row numbers must be less than matrix order.\n");
            return;
        }

    printf("\nResultant matrix is:\n"); //print the array in interchange,c
    printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",c[i][j]); 
            }
         printf("\n");
        }
}

void elem(float b[10][10],int m,int n)
{
    int ch;
    do
    {
        printf("\n1:Row interchange\t 2:Exit elementary transformations\n\nEnter the choice:");
        scanf("%d",&ch);  //get user input to decide which operation to perform (there are more operations in actual code)

        switch(ch)
        {
            case 1: interchange(b,m,n);
                    break;

            case 2: printf("\nExiting elementary transformations.\n");
                    break;
        }

    }while(ch!=2);
}

int main()
{
    float a[10][10];
    int m,n,i,j;
    printf("Enter the order of the matrix:");
    scanf("%d%d",&m,&n);
    printf("Enter the matrix elements:");
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            scanf("%f",&a[i][j]);
        }
    }

        //print the entered array a
    printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",a[i][j]); 
            }
         printf("\n");
        }

    elem(a,m,n);

        //print the original array in main()   
        printf("\n");
    for(i=0;i<m;i++)
        {for(j=0;j<n;j++)
            {
                printf("%f\t",a[i][j]); 
            }
         printf("\n");
        }
}

This is the output I got:

Enter the order of the matrix:2 2
Enter the matrix elements:1 2 3 4

1.000000        2.000000
3.000000        4.000000

1:Row interchange        2:Exit elementary transformations

Enter the choice:1

Enter the two row numbers to interchange:1 2

Resultant matrix is:

3.000000        4.000000
1.000000        2.000000

1:Row interchange        2:Exit elementary transformations

Enter the choice:2

Exiting elementary transformations.

3.000000        4.000000
1.000000        2.000000

Sorry for the shabby code, I salvaged it from a larger file.

klutt
  • 30,332
  • 17
  • 55
  • 95
Anchith Acharya
  • 369
  • 1
  • 4
  • 16
  • 2
    In C, all arrays are passed as a pointer of some sort — so the called function can modify the array in the calling function (unless there are `const` qualifiers on the declaration in the function to prevent such modifications). Arrays are not copied in bulk. – Jonathan Leffler Jun 05 '19 at 15:41
  • 1
    FYI, the "value" of an array id in an expression (such as an argument to a function) is the base address of the first element. Think about that. If you want to really pass an array by value, bury it in a structure. – WhozCraig Jun 05 '19 at 15:41
  • 1
    Array expressions "decay" to pointer expressions unless they're the operands of the `sizeof` or unary `&` operators - when you pass `a` to `elem`, it is implicitly converted to a pointer (`int (*a)[10]`) to the first element (`&a[0]`) when the argument list is evaluated, so all `elem` receives is a pointer value. It is not possible to pass an array expression as a parameter and have it interpreted as an array in the called function. – John Bode Jun 05 '19 at 16:14
  • 1
    There is a bug in the `if` condition `if((--p – Ian Abbott Jun 05 '19 at 16:23
  • @Ian Abbot Indeed! I had only executed the program with square matrices until now, so I had never noticed the bug. Thanks for pointing it out! – Anchith Acharya Jun 05 '19 at 18:17

2 Answers2

6

For function arguments, you can't pass arrays "by value".

When the compiler sees the argument declaration float c[10][10], it translates it as float (*c)[10].

So what is passed is a pointer (to the first element of the array). You modify the memory that the pointer is pointing to, which reflect back in the calling function.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
5

Why is this so?

Yes, you ARE passing it "by value", but you have to understand what that means in C. When you pass an array to a function, it will decay to a pointer. That pointer is then passed by value, but the value is the address to the first element in the array.

and what can I do to make the array in main() remain unchanged?

A few different things, depending on what you want. You could create a temporary array in the function and then copy all the values. Replace the start with:

void interchange(const float arr[10][10],int m,int n) {
    float c[10][10];
    for(int i=0; i<10; i++)
        for(int j=0; j<10; j++)
            c[i][j]=arr[i][j];

and your code would work the way you want, provided that there's no other bugs. The addition of const has the effect that you would get a compiler error if you tried to assign an element in arr to something.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • Shouldn't that be `float c[10][10];`? Another option is to use a 1-D array `char row[10]`to store the matrix row indices instead of copying the whole matrix. – Ian Abbott Jun 05 '19 at 16:16
  • @IanAbbott You're absolutely correct. Fixed it. – klutt Jun 05 '19 at 16:54
  • Thank you. I will try this this tomorrow and update the results, although I cannot use const because in my main program, the array needs to be manipulated quite a few times. I will try adding the temporary array though. – Anchith Acharya Jun 05 '19 at 18:11