Home > database >  Struct passed by value is modified in function in c
Struct passed by value is modified in function in c

Time:11-05

I have this code were i need to sort an array of struct without modifying it. I passed the array of struct by value and i used an int array with indexes to sort the struct. To sort the array i also need to sort the struct, which is passed by value in the function, if i am not wrong, if you modify a value passed by value in a funtion it still is the same in the main, but in the main it changes, and when i try to print the struct array using the sorted array of indexes it doesn't print it sorted becouse the array of struct is sorted(as i said before, to sort the indexes i need to modify the array of struct).

I expected that the struct array doesn't get modified if i pass it as value.

this is the function, after this will be the chunk of code where i use the function.

void Opartenza(struct Corse c[], int d, int **O)
{
    int temp = 0;
    O[0] = (int *)malloc(d * sizeof(int));
    for(int i = 0; i < d; i  )
        O[0][i] = i;
    for(int i = 0; i < d; i  )
    {
        for(int j = 0; j < d - 1; j  )
        {
            if(strcmp(c[j].partenza, c[j   1].partenza) > 0)
            {
                temp = O[0][j];
                O[0][j] = O[0][j   1];
                O[0][j   1] = temp;
                c[d] = c[j];
                c[j] = c[j   1];
                c[j   1] = c[d];
            }
        }
    }
}
case r_o_partenza:
                Opartenza(corse, dim, &Ordinamento);
                for(int i = 0; i < dim; i  )
                    printf("%s\n", corse[i].partenza);
                break;

As you see i tried to print the array of struct, and it is sorted as the array of indexes.

CodePudding user response:

In C arrays are always passed by reference, no matter what, as internally indexing an array compiles down to pointer arithmetics. That means, that passing an array with array notation or a pointer to an array, really boils down to the same thing. If you really want your array to not be modified copy it first.

CodePudding user response:

In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the passed pointer you have a direct access to the object pointed to by the pointer. Here is a demonstration program

#include <stdio.h>

enum { N = 10 };

void f( const int ( *pa )[N] )
{
    printf( "The size of the passed array is %zu\n", sizeof( *pa ) );
}

int main( void )
{
    int a[N];

    f( &a );
}

The program output might look like

The size of the passed array is 40

In C arrays are non-modifiable lvalues. So even if you will pass an array by reference you can not change it. You can change only its elements. That is the assignment operator is not defined for arrays.

You may not write for example

char a[1] = { 'a' };
char b[1] = { 'b' };

a = b;

From the C Standard (6.3.2.1 Lvalues, arrays, and function designators

1 An lvalue is an expression (with an object type other than void) that potentially designates an object;65) if an lvalue does not designate an object when it is evaluated, the behavior is undefined. When an object is said to have a particular type, the type is specified by the lvalue used to designate the object. A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.)

On the other hand, you can change elements of an array if the array is not constant qualified.

Array designators used in expressions (with rare exceptions) are implicitly converted to pointers to their first element.

From the C Standard (6.3.2.1 Lvalues, arrays, and function designators

3 Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

So when you pass an array by value then used as an argument expression it is i,plicitly converted to a pointer to its first element.

Also function parameters having array types are also adjusted by the compiler to pointers to array element types.

For example these function declarations

void f( int a[100] );
void f( int a[10] );
void f( int a[1] );
void f( int a[] );
void f( int *a );

are equivalent and declare the same one function.

So if you will pass an array by value then it will be implicitly converted to a pointer to its first element and using the pointer to the first element of the passed array and the pointer arithmetic you can change any element of the passed array.

  • Related