数组名、&数组名、指针;函数指针

问题引出:https://freeline.blog.csdn.net/article/details/116484020

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int a[5] = {1,2,3,4,5}; // 000000000065FE00 是十进制的 6684160
                            // 000000000065FE14 是十进制的 6684180
	
	printf("a = %p\n",a); //a = 000000000065FE00
	
	printf("*a_d = %d\n",*a); // *a_d = 1
	
	printf("*a_p = %p\n",*a); // *a_p = 0000000000000001
	
	printf("&a = %p\n",(&a)); // &a = 000000000065FE00
	 //
	printf("*(&a) = %p\n",*(&a)); // *(&a) = 000000000065FE00
	
	printf("&a+1 = %p\n",(&a+1)); // &a+1 = 000000000065FE14
		
	printf(" *(&a) = %d\n",*(&a)); //  *(&a) = 6684160
		
	printf(" **(&a) = %d\n",**(&a)); //  **(&a) = 1
	
	printf(" *(&a + 1) = %d\n",*(&a + 1)); //  *(&a + 1) = 6684180
	
	printf(" **(&a + 1) = %d\n",**(&a + 1)); //  **(&a + 1) = 0
	
	printf("*a = %d\n",(*a)); // *a = 1
	
	printf("*(a + 1) = %d\n",(*(a + 1))); // *(a + 1) = 2
	
*(&a) = 000000000065FE00, a = 000000000065FE00, 
 &a[0] =000000000065FE00,以上三个都是指向数组首元素维度的指针
&a = 000000000065FE00,指向整个数组维度的指针
	return 0;	
	
}

逐条分析:

(1)a是数组名,a的值是数组第一个元素a[0]的地址,从第一条的结果来看,说明a这个数组的地址(也就是a[0]的地址,是000000000065FE00)。

(2)*a,相当于取a[0]地址上的值,自然将会得到a[0]的值,也就是1。

(3)用%p打印*a,是为了表示%p和%d的区别是只是用十六进制打印还是用十进制打印,其数值是不受影响的。用%x打印地址也是16进制,数值和%p打印出来的一样,只是形式不同:比如打印同一个地址时:%x为65fe00,%p为000000000065FE00。

%号后的字母,表示对同一数值打印方式有区别,但操作对象都是同一个数值。

(4)&a,相当于取数组a的地址,数组的地址就是数组首元素的地址,

所以&a = &a[0] = a,数组名 = 数组首元素的地址 = 数组的地址。

(5)*(&a):错误想法:&a,a = &a[0],相当于&a[0],所以*(&a[0]) = a[0],错!

a表示的是数组的地址,在数值上是a[0]的地址,但是其也是整个数组的地址,对于数组来说,数组的地址也是数组第一个元素的地址,a与&a,这两者在数值上相同,在维度上不同。&a,相当于取整个数组的地址,&a实际上是一个指向整个数组的指针,是int* *类型的。a,相当于指向数组第一个元素的指针,是int*类型的。数值上相同,但意义上未必相同。

所以,*(&a),&a是一个指向数组的指针,对&a进行*操作,将会得到数组a的地址,也就是&a[0]。

(6)&a + 1,&a是以整个数组作为颗粒度的,所以&a + 1,会增加数组a的大小个,所以会在a的值上增加sizeof(int)*sizeof(a)的大小,也就是4 * 5 = 20。

(7)同 (5)

(8)**(&a),相当于取a[0]的值,也就是1。&a是一个指向数组(颗粒度)的指针,*(&a),取数组的地址,相当于一个指向数组首元素的指针;**(&a),相当于得到数组首元素的值。

(9)*(&a + 1),&a + 1,是指向数组维度的,(&a + 1)相当于指向与数组a在内存中邻近数组的指针,*(&a  + 1)相当于指向这个邻近数组首元素的指针,也是一个地址,并且这个地址和前面的(6)是相同的数值。

(10)**(&a + 1),得到的值为a的邻近数组的首元素的值,这个和内存有关,可能是随机的值。

(11)*a,a是指向数组首元素的指针,在数值上等于首元素的地址,所以*a = a[0] = 1。

(12)*(a + 1):a是指向数组首元素的指针,是数组元素维度的,所以a + 1指向的是数组的下一个元素,也就是a[1]的地址。

数组名与首元素的关系:数组名是指向首元素的指针,数组名的值是首元素的地址,数组名是以数组元素为颗粒度的指针常量。

注意,a是指向数组元素维度的,指向了数组首元素的地址,&a是指向整个数组维度的,相当于有些二级指针的意思,两者数值相同,含义不同,所以进行相同的操作时,得到的结果也是不同的。

内容补充,建议看看:数组名和数组名取地址& 的区别_wangkeyen的博客-CSDN博客_数组名作为类型,作为地址,对数组名取地址的区别

实际上,不用过分纠结于为什么数组名也是等于数组的地址,因为C语言中就是这么规定的,数组名本身的取值,在数值上就是数组的地址,就是数组首元素的地址,数组名是面向数组元素的指针,&a是面向数组的指针,但是两者的维度是不同的,在数值上是相同的。

与数组相同的,函数名也表示函数所在的地址,比如有一个函数int Add(int, int),其中,Add = &Add,这两者在数值上也是相同的,在C语言中,函数名的数值就是函数的地址。

函数指针的相关内容参考:

C语言函数名、&函数名、*函数名_chen_dunyun的博客-CSDN博客_函数名

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小哇123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值