args和& args之间的区别是什么?

时间:2014-11-25 07:04:58

标签: c arrays

这是我的代码片段

    #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是数组)之间的区别是什么,为什么我从第一个片段获得不同的地址? 谢谢!

5 个答案:

答案 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的地址。但&aa的地址,而不是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中做到这一点的原因 - 因为一个是指针分配了内存,因此可以像其他变量一样改变它的值,另一个只是它的第一个元素的占位符,因此无法改变它的值。

我希望现在很清楚为什么&bb相同 - 因为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的地址,而不管内容如何。