1、先把问题摆出来
参考demo:
1#include 2#include 3 4/************************************ 5*fuction:测试demo 6*author:(公众号:最后一个bug) 7***********************************/ 8intmain(intargc,char*argv[]){ 9inta=10; 10int*ptr=&a; 11int**ptrptr=&ptr; 12 13printf(*ptr=%d ,*ptr); 14printf(**ptrptr=%d ,**ptrptr); 15printf(**((int**)ptr)=%d ,**((int**)ptr)); 16printf(欢迎关注公众号:最后一个bug ); 17return0; 18}
运行结果:
现象描述:
大家可以看到当试图输出**((int **)ptr)的时候程序奔溃了,其实在bug菌刚开始学习c的时候也是遇到了这个问题,最终理解清楚了就自然明白了。粗暴点就把((int **)ptr);*((int **)ptr);**((int **)ptr)都尝试着打印出来分析分析。
所以bug菌在下面把指针的一些知识点都跟大家讲解一下,形成系统的知识,避免一些小伙伴仅学习了一些碎片而一知半解。
2、二级指针的使用
1
多级指针 其实多级指针在嵌入式程序中的应用还是相对比较少的,超过3级的bug菌仅仅只在一个特殊的索引功能里面使用过。 这里重点看看一、二级,毕竟二级指针与我们的二维数据结合使用,二维素组在图形、矩阵、算法等等方面还是使用非常广泛的。
2
一级指针 指针其实广义的讲它也是一种数据类型,所以所谓的int* ptr;其中int* 就是变量ptr的类型,那么ptr就是我们常说的指针变量。
demo:
1#include 2#include 3/************************************ 4*fuction:测试demo 5*author:(公众号:最后一个bug) 6***********************************/ 7intmain(intargc,char*argv[]){ 8inta=10; 9int*ptr=&a; 10 11printf(a=%d ,a); 12printf(&ptr=0x%x ,&ptr); 13printf(&a=0x%x ,&a); 14printf(ptr=0x%x ,ptr); 15printf(*ptr=%d ,*ptr); 16 17printf(欢迎关注公众号:最后一个bug ); 18return0; 19}
运行结果:
图解:
分析一下:
ptr既然是变量,变量存于内存中,那么就一定有其地址,如上图所示ptr位于0x28fee8地址处,其中其ptr里面保存的就是蓝色区域中的地址,也就是a变量所在的地址,所以&a与ptr是相等的。
*ptr就很好理解了,你可以把*ptr看成一个变量,其类型为int,其变量位于ptr值所在的内存地址处,即0x28feec处的int变量与定义的int a刚好一致。
3
二级指针 如果大家已经理解了一级指针,二级指针也就顺理成章了,来看看下面的小程序:
demo:
1#include 2#include 3/************************************ 4*fuction:测试demo 5*author:(公众号:最后一个bug) 6***********************************/ 7intmain(intargc,char*argv[]){ 8inta=10; 9int*ptr=&a; 10int**ptrptr=&ptr; 11 12printf(a=%d ,a); 13 14printf(&ptrptr=0x%x ,&ptrptr); 15 16printf(ptrptr=0x%x ,ptrptr); 17printf(&*ptrptr=0x%x ,&*ptrptr); 18printf(&ptr=0x%x ,&ptr); 19 20printf(*ptrptr=0x%x ,*ptrptr); 21printf(ptr=0x%x ,ptr); 22 23printf(*ptr=%d ,*ptr); 24printf(**ptrptr=%d ,**ptrptr); 25 26printf(欢迎关注公众号:最后一个bug ); 27return0; 28}
运行结果:
图解:
分析一下:
通过上图来看ptrptr也是一个变量,其类型为int**,变量肯定有内存,其地址就是0x28fee4,其变量保存的值是0x28fee8(即ptr的地址)。
那么*ptrptr,同样跟一级指针一致,把*ptrptr看成一个变量,也就是在ptrptr的值0x28feec8地址处的一个int*类型的变量,且该变量的值是0x28feec,其自身的地址为0x28fee8。
同样对于**ptrptr也看成变量,也就是*ptrptr的值0x28feec地址处的一个int类型的变量,那么此时该变量与a是相等的。
最后在解释一下&*ptrptr,由于*ptrptr一个变量,&*ptrptr表示该变量的地址即0x28fee8,然而该值刚好也是ptrptr变量的值,所以&*ptrptr =ptrptr。
3、是时候解答前面的问题了
参考demo:
1#include 2#include 3 4/************************************ 5*fuction:测试demo 6*author:(公众号:最后一个bug) 7***********************************/ 8intmain(intargc,char*argv[]){ 9inta=10; 10int*ptr=&a; 11int**ptrptr=&ptr; 12 13printf(*ptr=%d ,*ptr); 14printf(**ptrptr=%d ,**ptrptr); 15printf(**((int**)ptr)=%d ,**((int**)ptr)); 16printf(欢迎关注公众号:最后一个bug ); 17return0; 18}
分析一下:
我们知道问题出在**(int**)ptr,不太理解的小伙伴总是觉得,我已经强制类型转化为二级指针了,前面只需要用**获得最后的值即可,怎么就不行呢? 我知道这里有问题我就是不理解为什么?
那我们一起通过前面的知识来分析分析。同样把ptr看成是变量,变量的值并不会跟随强制类型而发生改变。强制类型仅仅只是改变了获取内存中数据的方式,并没有改变内存中的数据。下面图解一下:
所以本例子中对于强制类型转化中的**(int*****)ptr,无论强制类型转化为几级指针都没有丝毫意义,因为变量本身的值没有发生变化!所以强制类型转化以后第二个*便会指向出问题,从而导致访问了不正确的内存空间而程序奔溃。
多级指针强制类型转化的目的大部分都是为了满足编译器检查指针层级操作逻辑是否有误。
以后大家对于多级指针的分析不太熟练的话可以跟bug菌一样画画图分析分析,基本上一些理解上的问题就迎刃而解了。
4、最后小结
指针的理解就为大家讲解到这里了,如果你对指针还有畏惧感,那就只有一个可能,使用得太少了,多加练习自然生巧!
自动驾驶六大趋势有哪些?
土壤墒情实时监测系统有效促进了农作物的生长发育
如何使用串行EEPROM的仿真模式和编码方案来解决问题
连续3年!君鉴科技成为是德科技首选租赁合作伙伴
谷歌、IBM、微软的人工智能处理器
C进阶技巧:二级指针问题
CEVA音频前端软件解决方案通过Alexa语音服务(AVS)认证
第82届中国电子展今天在沪开幕
是德科技PCIe5.0协议分析仪荣获全球电子成就奖
基于RFID 系统的 CNG 车辆的安全性和准确性套件开发设计
应急指挥中心调度平台系统的解决方案该怎么做
5条青少年学习无人机悬停必懂知识,建议收藏
快充Quick Charge 3.0 新一代旗舰机王必配
光宝科今年第一季营收与获利相较去年可望有大幅成长
思科财报超出预期,净利润24亿美元,股价上涨近4%
中国移动、电信取得5G商用“重大突破”
112G 以太网 PHY 的设计挑战和演进之路
几张图了解360N5发布会:骁龙653+6GB,致敬诺基亚
智能环境检测面板为实现智能家居提供巨大助力
电气传动优缺点 电气传动方式有哪些