c语言取地址符与数组之间联系

c语言取地址符与数组之间联系

大家都知道在c语言中,“&”放在在变量前有取得该变量内存地址的意思,那如果将“&”符号放在数组之前又会有怎样的变化呢?

数组名与指针的关系

在c语言中,数组名为该数组首元素的地址,如:
int a[3]={1,2,3},a的值为0x7ffee86cbaec,该值与a[0]的地址相同。

int a[3]={1,2,3};

    printf("the array adress is %p.\n",a); //the array adress is 0x7ffee86cbaec
    printf("the a[0] is %p.\n",&a[0]); //the a[0] is 0x7ffee022daec

在对a[0]时用到了取址符“&”,因为a[0]是特定的值。
而在二维数组中,数组名虽然还是数组首元素的指针,但是在指针偏移单位及解引用上有着不同。
假设b数组为有4个子数组,每个数组又内含了3个数值,

int b[4][3]={{1,2,3},{4,5,6},{7,8,9},{11,12,13}};

此时数组名b的值为0x7ffee8b32ab0,虽然仍与b[0][0]的地址相同,但是在编译器看来,这两个仍然存在不同。
数组名b实际上是子数组{1,2,3}的地址,b+1相当于指针增加3(size of int)个 单位*,也就是下个子数组{7,8,9}的内存地址。
如果将二维数组名作为实参,代入到形参中,需要将形参设置为 int (* pt) [3],也就是说pt是指向含有三个元素数组的指针,该指针指向的内存大小为 3*(size of int)。
在对数组名解引用时,*b意味着对数组首元素b[0]取值,但是b[0]是子数组,所以b[0]值就是含3个元素数组的内存地址,所以需要再解引用一次,才能取到b[0]中第一个元素的值1。


    printf("%p.\n",*b); // 0x7ffeeb3acab0
    printf("%d.\n",**b); // 1

如果想取到第三个子数组中第二个值,需要先将数组名(地址)向右偏移两个单位,解引用第一次,取得第三个子数组中的首元素地址。然后在该子数组中再向右偏移一个单位,取得第二个值的内存地址,最后再解引用该地址,得到值8.

printf("%d.\n",*(*(b+2)+1)); // 8
printf("%d.\n",b[2][1]); // 8

虽然两个方法取得的值都一样,第二种更简便,但是用指针来思考多维数组,能够更加深理解。

数组与取值符

在说明数组名和指针的关系后,现在来说一下如果在数组名前使用取址符会怎么样。
还是用b数组。

int b[4][3]={{1,2,3},{4,5,6},{7,8,9},{11,12,13}};

对于指针变量来说。如 int * pt,pt=b[0],我们可以说pt是指向int类型数组b[0]中首元素1的内存地址。pt自身的内存地址与b并不一致,指针长度为4字节,在64位操作系统下那么就都是8字节,长度与系统的寻址能力有关。pt储存的值即为b[0]的内存地址。

int * pt;

    pt=b[0];
    printf("%p.\n",pt); //数组地址 0x7ffee9202ab0
    printf("%p.\n",&pt); // 指针自身的地址 0x7ffee33a3aa0

现在在数组前加一个取值符

	printf("%p.\n",&b); //0x7ffeee45aab0
    printf("%p.\n",&b[0]); // 0x7ffeee45aab0
    printf("%p.\n",b); // 0x7ffeee45aab0

可以看到三个内存地址都是一致的,也就是说数组、数组名与&数组名 都是同一个值。c语言中,数组名是常量,编译器没有为数组名分配空间,但编译器对数组名做了特殊处理,所以数组名是不能作为左值,不能自增自减。在c编译器中,将 &+数组 视为取数组区域的地址,这里做一个实验验证一下

i	nt * pt;
    int (* pr) [3];

    pt=&b[0];
    pr=&b[0];

编译时报了错,错误原因为 “不匹配指针类型”,问题就在于&b[0]虽然是数组首元素的地址,但要把整个数组内存区域看作一个单位,这个区域包含三个元素,所以pr=&b[0]这个是对的。pr是指向三个int类型元素内存地址的指针。
再用指针偏移实验一下:

printf("%d.\n",**(&b[0]+1)); //  4 

可以看到这个值与用 **(b+1)相同,所以印证了&+数组,是将该数组内存区域看作一个单位。&b[0]+1,向右偏移一个单位到了下个数组b[1],解引用1次取得数组中首元素的地址(一个int类型),然后再解引用取得该值。

概括的来说&(b[i])其实与b+i相同,都是子数组首元素地址,但是占用了一个数组单位的区域。

以上内容大多为为本人手打,部分引用了https://blog.csdn.net/lerenceray/article/details/8983290内容,因为是本人第一次发博客,可能也会有错误,请大家指出

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值