这是我的代码片段
#include <stdio.h>
void change(int a[]){
printf("%p\n",&a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",&b);
change(b);
return 0;
}
我运行它,然后得到
后的结果 0x7fff5def1c60
0x7fff5def1c38
正如我们所看到的,实际参数地址与形式参数地址不同 然后我编辑了以下
#include <stdio.h>
void change(int a[]){
printf("%p\n",a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",b);
change(b);
return 0;
}
然后我得到了结果
0x7fff56501c60
0x7fff56501c60
所以看起来实际参数和形式参数具有相同的地址。 我很困惑,&amp; a和a(a是数组)之间的区别是什么,为什么我从第一个片段获得不同的地址? 谢谢!
答案 0 :(得分:4)
在:
printf("%p\n",&b);
您正在将地址打印到第一个阵列单元格。
在:
change(b);
,特别是:
void change(int a[]){
printf("%p\n",&a);
}
您正在打印变量a
的地址,该变量本身就是一个衰减的指针。所以它在语义上等同于:
void change(int* a){
printf("%p\n",&a);
}
要检索数组的第一个单元格,您需要将函数编写为:
void change(int* a){
printf("%p\n", a);
// ^^
}
答案 1 :(得分:2)
您可以认为a
是内存的起始地址array[1, 2]
。
还请注意a
是存储数组地址的变量。变量意味着它本身就在内存中。因此&a
是变量a
的地址。总而言之,内存中的地址&a
存储array[1,2]
的地址。
在第一种情况下,您将变量b
的地址传递给函数change
,以便函数变量a
存储变量b
的地址。但&a
是a
的地址,而不是a
的内容。这就是导致差异的原因。
答案 2 :(得分:1)
在main()
中,b是一个数组,如果从初始化得到,则为&b
表示数组的地址。
在change()
中,a是一个未知大小的数组,其参数作为指针处理。 &a
是此指针的地址。
在代码的第二个版本中,如果没有&
,则在两种情况下都会引用指针的值。
这里是C11标准的相关摘录:
6.5.3一元经营者,第3页:一元&amp;运算符产生其操作数的地址。
6.7.6.3函数声明符,第7页:参数声明为''数组'''应调整为''限定指针 type'',其中类型限定符(如果有)是指定的类型 数组类型派生的[和]。
答案 3 :(得分:1)
因为我认为答案到目前为止还不够,所以我会给出另一个答案:
b
与&b
之间没有区别,如果b
是数组。数组几乎就像一个指针,但不是100%。如您所知,指针是存储地址的变量。因此,当您创建指针p
时,您将创建一个新变量,然后为其指定一些地址。现在指针变量p
有一个地址,它的值也是一个地址。你可以用它做三件事:
- 使用p
获取&p
地址
- p
获取p
的值
- 使用p
*p
取消引用的值
使用数组ar
,它是不同的。它就像一个指针,但它是不一个存储地址的独特变量!通过创建数组,您只需为要存储的元素分配内存,但不用于存储这些元素地址的变量。变量ar
只是'代表'第一个元素的地址,但它不会保存在额外空间的某个地方;编译器确保将ar
转换为第一个元素的内存 - 这一点很重要。所以你能用它做的是:
- 使用ar
获取&ar
地址或使用ar
获取
- 使用ar
ar[0]
的值
这就是为什么在您的change
函数中,int a[]
与int *a
相同,但在您的主函数中,int b[]
不与int *b
相同。后者为地址分配内存,而第一个只为指定数量的元素创建内存,只使用b
作为这些元素的第一个地址的占位符 - 有否为第一个元素的地址分配的额外内存,就像使用指针一样。
这也是为什么在main
中你不能做b = some_pointer
,但你可以在change
中做到这一点的原因 - 因为一个是指针分配了内存,因此可以像其他变量一样改变它的值,另一个只是它的第一个元素的占位符,因此无法改变它的值。
我希望现在很清楚为什么&b
与b
相同 - 因为b
不是一个在内存中有位置的独特变量,所以你不能要求它的地址 - 它只会告诉你b
代表的地址。
答案 4 :(得分:0)
“&amp;” operator返回变量的地址,printf中的“%p”结构返回指针的地址。
在您的示例中,main()中的这些调用是等效的:
printf("%p\n",b);
printf("%p\n",&b);
两者都返回b的内存位置,在你的例子中是0x7fff56501c60
定义函数时,引入局部变量a:
void change(int a[]){
这是一个指针(相当于int * a)并且有自己的内存地址。
当你在函数内调用它时:
printf("%p\n",a);
你得到与上面相同的东西:b的地址:指针b的值被复制到a,而printf告诉你它指向的位置。
但是如果你这样做:
printf("%p\n",&a);
然后你得到局部变量a的地址,它与b不同。内部的内容并不重要,在您的示例中,b的值甚至不被函数“更改”使用,您也可以运行:
#include <stdio.h>
void change(int a[]){
printf("%p\n",&a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",&b);
change((int *)0);
return 0;
}
这使用Nullpointer运行“更改”,它仍然等同于您的第一个示例:“更改”只打印出局部变量a的地址,而不管内容如何。