简体   繁体   English

a和&a在C中作为函数参数传递的数组不同

[英]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? 为什么作为函数参数传递的数组的a和&a的值不同? b and &b do not differ for an array defined within a function body. b和&b对于函数体内定义的数组没有区别。 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() : 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() : 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. */
                          /* 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 ) . 基本上当你输入void foo( int a[2] )你正在以一种有趣的方式写入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 . 我必须从标准中寻找特定的引用,但是当分析函数签名时,类型为T的N个元素的类型数组的参数被转换为指向T的指针 When you later type foo(a) , a decays into a pointer to the address of the first element, which is copied. 当以后类型foo(a) a衰变成一个指针的第一个元素,这是复制的地址。 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 . foo你将指针的值与main数组a第一个元素的值与foo指针a的地址进行比较。

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. 另一方面,在同一个函数中,当数组在foo内的b范围内时,数组的地址( &b )和数组的第一个元素的地址(可以通过键入来强制衰减来获得) b )是相同的地址。

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. a计算传递给函数的第一个元素&(a[0])的地址。

If you use &a the address of the array as a whole is taken. 如果你使用&a作为整体的数组的地址。 It has the same value as &(a[0]) but the type is different. 它与&(a[0])具有相同的值,但类型不同。 &(a[0]) has type "pointer to basetype" whereas &a has type "pointer to array of basetype" . &(a[0])具有类型“指向basetype的指针”,&a具有类型“指向basetype数组的指针”

Inside the function &a is something different. 在函数内部&a是不同的东西。 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. 这里a是一个“指向basetype的指针”,所以&a的类型是“指向basetype指针的指针” ,你看到的地址是堆栈上指针的地址,而不是原始数组的地址。

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. 当您使用& with function参数时,您将获得该值的地址。 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


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM