a及&;在C中作为函数参数传递的数组的

a及&;在C中作为函数参数传递的数组的,c,arrays,C,Arrays,对于作为函数参数传递的数组,为什么a和&a的值不同?对于函数体中定义的数组,b和b没有区别。守则如下: 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; } 编辑: 因此,经过所有讨论,我了解到以下情况: 在main()中: 在f

对于作为函数参数传递的数组,为什么a和&a的值不同?对于函数体中定义的数组,b和b没有区别。守则如下:

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;
}
编辑:
因此,经过所有讨论,我了解到以下情况:

main()
中:

foo()
中:


基本上,当您键入
void foo(int a[2])
时,您的书写方式很有趣
void foo(int*a)

我必须从标准中查找特定的引用,但是当分析函数签名时,类型为T的N个元素的数组类型的参数转换为指向T的指针。当您稍后键入
foo(a)
时,
a
衰减为指向复制的第一个元素的地址的指针。在
foo
内部,您将
main
中指向数组
a
的第一个元素的指针的值与
foo
中的指针
a
的地址进行比较

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

关于未来的两条简单信息:

  • 函数签名中的数组被解释为指针:避免使用这种语法,使用指针语法,您会得到更少的惊喜
  • 在大多数上下文中,表示数组衰减为指向第一个元素的指针的标识符
例如:

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)
}

数组不是指针。它几乎在所有上下文中都计算为指针,但其中一个显著的例外是
&
运算符

如果你调用一个以数组为参数的函数

f(a);
那里的
a
计算为传递给函数的第一个元素
&(a[0])
的地址

如果使用
&a
则取整个阵列的地址。它与
&(a[0])
具有相同的值,但类型不同<代码>&(a[0])的类型为“指向基类型的指针”,而
&a
的类型为“指向基类型的数组的指针”


函数
&a
的内部是不同的。这里
a
是“指向基类型的指针”,因此
&a
是“指向基类型的指针”类型,您看到的地址是堆栈上指针的地址,而不是原始数组的地址。

当您通过引用函数传递参数时,从技术上讲,您将元素的地址放入函数调用堆栈中。将
&
与函数参数一起使用时,将获得该值的地址。我将尝试举例说明(所有地址都是任意的,仅供演示):


@Nitz是一个很好的问题。你的意思是在你的代码中不能将foo()称为foo(&a)。@算法学家:虽然我不认为这是问题的意思,但事实是你不能,因为类型不匹配。在
main
中,
a
衰减为
&a[0]
,类型为
int*
,而
&a
类型为
int(*)[2]
@Algorithmist,当我在上面用foo(&a)运行代码时,不会(&a)衰减为类似的指针吗?@nitzs它成功了。但是@david是个专家,所以他肯定是对的。原型转换的另一个可能令人惊讶的效果是:在
foo
sizeof(a)!=sizeof(b)
@nitzs:我已经更新了答案,如果您需要进一步的解释,我可以尝试重写它,或者清除任何特定的疑问。当我调用foo(&a)和foo(a)时,我没有发现它们的o/p有任何细微的区别。您能看到一个示例,我们可以区分&a和a(a是数组名称时)在输出方面的任何函数调用中。@Algorithmist:
void foo(int*){}int main(){int a[2];foo(&a);printf(“%d!=%d\n”、sizeof(*a)、sizeof(*a));}
。这将在调用
foo
时给您一个指针类型转换无效的警告(可能是printf中的其他警告),并且运行程序的输出将包含两个不同的数字,其中第二个数字是第一个数值的两倍(可能是“4!=8”)你的意思是&a在函数内部和外部都不同。这里有点混乱,因为
a
-是形式参数和实际参数的名称。为了澄清,可能最好对实际参数使用不同的名称:`intb[2];foo(b)`-这里我们将
b
传递给函数。在函数体中,可以通过形式参数
a
访问它。所以
&a!=&b
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)
}
f(a);
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


}