C语言基础---16.看图学多级指针---入门篇

如果一级指针还不是很熟悉的同学,可参考博文:C—看图学指针—小白基础入门篇

1.一级指针图示:

在这里插入图片描述

  • 在堆内存中保存数据的地址为00B8A000
  • 指针b在栈内存的地址为00B8A004,但指针变量b会保存堆内存的地址00B8A000,方便指针找到堆内存
  • *b的过程是先找到指针变量b对应的堆内存地址,然后再算出来这个地址对应的值,即为10



2.二级指针的图示:

注意,二级指针此处用**c定义二级指针,只能用2个*

在这里插入图片描述

  • 二级指针c,因为指向了一级指针b,根据一级指针的原理,C指针(指针变量c存放具体的地址值),应该存放的是b指针的内存地址,即为00B8A004
  • 二级指针**c指向一级指针b,按照一级指针的原理,b变量存放的是其指向内存的地址,**c指向b,所以c(c指针变量才能存储值,c指针本身只有指向关系)指针存放的是b指针的内存地址 (很重要!很重要!很重要!)
  • 栈内存上存放的都是内存地址,因为**c指向b,b指向a(堆内存存放的是具体的数值),所以b取值的话,直接找到堆内存,**c取值的话,先找到b,最终还是找到a变量。
  • 无论是二级指针还是多级指针,都按照二部分划分,指针类型(int * 或int ** 或int ***)和指针变量 (p),指针变量赋值保存被指向的内存地址,指针类型负责规定是一级指针、二级指针、或三级指针



3.代码验证–不同级别指针中p,&p,*p的含义


int main() {
	int a = 10;
	int* b = &a;
	int** c = &b;
	printf("a的值:%d\n", a);	// a的实际值
	printf("a的地址:%p\n", &a); // a的地址值
	printf("==================\n");

	printf("b的地址:%p\n", b);   //一级指针b指向变量a,那b保存的值为a的地址值
	printf("&b的地址:%p\n", &b); //一级指针b,对应的&b是指针b的真实地址,
	printf("*b的值:%d\n", *b);   //指针b指向变量的真实的值
	printf("==================\n");

	printf("c的地址:%p\n", c);   // 二级指针的指针变量的值为:被指向指针的真实地址,即b的真实地址&b
	printf("&c的地址:%p\n", &c); // 二级指针c,本身的地址&c
	printf("*c的地址:%p\n", *c); // 二级指针**c,*c保存的是b指针的地址值&b,
	printf("**c的值:%d\n", **c)  // 因为*c保存的是&b,那么对**c取值相当于*b取值

	return 0;
}


a的值:10
a的地址:0133FC3C
==================
b的地址:0133FC3C		// b的值,就是b保存的a的地址值
&b的地址:0133FC30		// b本身的地址值
*b的值:10
==================
c的地址:0133FC30	  //c的值,就是c保存的b指针的地址值
&c的地址:0133FC24	  // c本身的地址值
*c的地址:0133FC3C    // 注意,*c最终是首元素的地址!!!
**c的值:10			 // b指针指向了a的首地址,所以*b等于a的首个元素的值。而c又指向了b,说明c指向的是b的首地址,b又指向a,所以,最终通过**c可以找到a的元素的值。



4.代码验证—多级指针中,指针地址之间的相互关系


int main() {
	int a = 10;
	int* b = &a;
	int** c = &b;
	int*** d = &c;

	printf("a指针的地址:%p\n", &a); 
	printf("b指针的地址:%p\n", &b); 
	printf("c指针的地址:%p\n", &c); 
	printf("d指针的地址:%p\n", &d); 
	printf("==================\n");
	printf("**d的地址:%p\n", **d); 
	printf("*d的地址:%p\n", *d); 
	printf("d的地址:%p\n", d); 
	printf("==================\n");
	printf("*b的值:%d\n", *b);
	printf("**c的值:%d\n", **c);
	printf("***d的值:%d\n", ***d);

	return 0;
}


a指针的地址:00EFFCA8
b指针的地址:00EFFC9C
c指针的地址:00EFFC90
d指针的地址:00EFFC84
==================
**d的地址:00EFFCA8
*d的地址:00EFFC9C
d的地址:00EFFC90
==================
*b的值:10
**c的值:10
***d的值:10

在这里插入图片描述

得到结论:

  • 无论是几级指针,只要对应多个*取值,都可以找到最终实际数组的首元素。例如三级指针 *** d,四级指针 **** e,最终都可以取到最终数组的首元素的值。
  • 三级指针中,***d是最终的首元素值,**d是首元素的地址,*d是一级指针的地址,d是二级指针的地址


5.二级指针中,如何拆分指针


int main() {
	int a = 10;
	int* p = &a;
	int** pp = &p;
	
	printf("a的地址:%p\n", &a);	  
	printf("a的值:%d\n", a);		  
	printf("==================\n");

	printf("p保存的地址:%p\n",  p);       
	printf("p本身的地址:%p\n",  &p);       
	printf("*p的值:%d\n",  *p);	
	printf("==================\n");

	printf("pp的地址:%p\n",  pp);       
	printf("*pp的地址:%p\n", *pp);
	printf("**pp的值:%d\n", **pp);


	return 0;
}


a的地址:00EFFE94
a的值:10
==================
p保存的地址:00EFFE94	// 这个是一级指针p保存的地址值,其实就是数组首元素的地址值
p本身的地址:00EFFE88	
*p的值:10
==================
pp的地址:00EFFE88	   
*pp的地址:00EFFE94	  // *pp保存的也是数组首元素的地址值
**pp的值:10

通过如上案例,我们得出如下结果:

在这里插入图片描述

  • 一级指针p保存了数组首元素地址
  • *pp的值也是首元素地址,可以把*pp看做是一级指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hello-alien

您的鼓励,是我最大的支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值