a and &a differs for an array passed as a function parameter in C
Why do the values of a and &a differ for a array passed as a function parameter? b and &b do not differ for an array defined within a function body. The code follows:
void foo(int a[2])
{
int b[2];
printf("%p %p\n", a, &a);
printf("%p %p\n", b, &b);
}
int main()
{
int a[2];
foo(a);
return 0;
}
EDIT:
So, after all the discussion, I understand the following is happening:In main()
:
int a[2]; /* define an array. */
foo(a); /* 'a' decays into a pointer to a[0] of type (int*). */
/* since C is pass-by-value, this pointer is replicated and */
/* a local copy of it is stored on the stack for use by foo(). */
In foo()
:
printf("%p %p\n", a, &a); /* 'a' is the value of the pointer that has been replicated, */
/* and it points to 'a[0]' in main() */
/* '&a' is the address of the replicated pointer on the stack开发者_Go百科. */
/* since the stack grows from higher to lower addresses, */
/* the value of '&a' is always lower than a. */
Basically when you type void foo( int a[2] )
you are writting in a funny way void foo( int *a )
.
I would have to look for the particular quote from the standard, but when a function signatures are being analyzed, an argument of type array of N elements of type T is converted to pointer to T. When you later type foo(a)
, a
decays into a pointer to the address of the first element, which is copied. Inside foo
you are comparing the value of a pointer to first element of the array a
in main
with the address of the pointer a
in foo
.
On the other hand, within the same function, when the array is within scope as b
inside foo
, the address of the array (&b
) and the address of the first element of the array (which can be obtained by forcing the decay by typing b
) are the same address.
Two simple pieces of information for the future:
- arrays in function signatures are interpreted as pointers: avoid that syntax and use the pointer syntax, you will get less surprises
- identifiers that denote an array decay into a pointer to the first element in most contexts
Example:
void foo( int a[2] ); // void foo( int *a );
int main() {
int x[2];
foo( x ); // foo( &x[0] ); -- inside foo, a is a copy of &x[0]
printf( "%d\n%d\n", (int)&a, (int)a ); // &a[0] which is the same address as &a
// (different type though)
}
An array is not a pointer. It evaluates to a pointer in almost all context, but one of the notable exceptions is the &
operator.
So if you call a function with an array as a parameter
f(a);
the a
there evaluates to the address of the first element &(a[0])
that is passed to the function.
If you use &a
the address of the array as a whole is taken. It has the same value as &(a[0])
but the type is different. &(a[0])
has type "pointer to basetype" whereas &a
has type "pointer to array of basetype".
Inside the function &a
is something different. Here a
is a "pointer to basetype" so &a
is of type "pointer to pointer to basetype" and the address that you see is the address of the pointer on the stack and not of your original array.
When you pass a parameter by reference to a function, you technically put an address of the element into function call stack. When you use &
with function parameter , you get the address of that value. I'll try to illustrate it (all addresses are arbitrary, for demonstration only):
int main()
{
int a[2] ; // a == &a == 0x001234
foo(a); // address of a (0x001234) goes to call stack,
// this value is stored in 0x00122C
// now inside foo(), &a == 0x00122C , a == 0x001234
}
精彩评论