#include <stdio.h>
int a(int m[], int x);
int main()
{
int n[3] = {1,2,3}, ab = 2;
printf("\nn =[ %d %d %d ]",n[0], n[1], n[2]);
printf("\nab = %d",ab);
a(n,ab);
printf("\nn =[ %d %d %d ]",n[0], n[1], n[2]);
printf("\nab = %d",ab);
return 0;
}
int a(int m[], int x)
{
m[0] = 6;
x = 99;
return 0;
}
Can anyone explain why in the main function array n[0] changes? And why int ab isn't changing?
CodePudding user response:
To change an object in a called function you need to pass it to the function by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer within the function you get a direct access to the original object and can change it.
The compiler adjusts a function parameter having an array type to pointer to the array element type.
So this function declaration
int a(int m[], int x);
is equivalent to
int a(int *m, int x);
On the other hand, when an array is used in expressions as for example as an argument expression it is implicitly (with rare exceptions) converted to pointer to its first element.
So this function call
a(n,ab);
is equivalent to
a( &n[0],ab);
Thus the function gets a pointer to the first element of the array and dereferencing the pointer and using the pointer arithmetic can change any element of the array.
An expression with the subscript operator like for example
m[i] = 6;
is equivalent to the expression
*( m i ) = 6;
As a result the i-th element of the original array will be changed within the function.
As for the variable ab
then it is not passed by reference. The function deals with a copy of the value of the variable ab
. Changing the copy does not influence on the value of the original variable.
You could also pass it to the function by reference declaring the function like
int a(int m[], int *px);
and then write within the function
*px = 99;
or
px[0] = 99;
In this case the function must be called like
a(n,&ab);
CodePudding user response:
C passes all function arguments by value - the formal parameters m
and x
in your a
function definition are different objects in memory than the actual parameters n
and ab
in the function call.
When you call a
, the expressions n
and ab
are evaluated, and the results of those evaluations are copied to the formal parameters m
and x
.
x
initially has the value from the evaluation of ab
(2
). It's then overwritten with the value 99
. Since x
and ab
are different objects, ab
is not affected.
m
initially has the value from the evaluation of n
, and this is where things get weird.
Array expressions are treated differently from expressions of any other type. Unless it is the operand of the sizeof
, _Alignof
, or unary &
operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T
" will be converted, or "decay", to an expression of type "pointer to T
" and the value of the expression will be the address of the first element of the array.
So when you write
a(n, ab);
that's equivalent to writing
a(&n[0], ab);
Similarly, the function prototype
int a(int m[], int ab )
is "adjusted" to
int a(int *m, int ab )
and the argument m
is actually pointer, not an array.
The array subscript operation a[i]
is defined as *(a i)
- given a starting address a
, offset i
elements (not bytes!) from that address and dereference the result. Even though the pointer variable m
is a different object in memory from n
, it stores the address of the first element of n
, writing a new value to m[i]
updates the corresponding n[i]
.