学习心态
指针其实跟一些运算符的表达式类似(例如i++,i–),它通过符号隐藏了内部的计算过程,只要学习者逐步的分解开,就很容易理解了。学习指针的时候,尽量想象底层硬件的工作方式,也能有助理解。
为什么会觉得指针难?
因为指针在现在的高级语言上基本不使用了,不使用的东西就会觉得很遥远、很神秘且难。但是只要你经常使用C语言编程,你就不会觉得难。
目标
- 理解指针的相关概念
- 清楚理解值传递和引用传递的区别
- 什么场景下需要用到指针?
- 引用传递
- 早期的计算机硬件,为什么需要指针这种语法?
- 理解指针变量、指针函数、指针参数
指针相关的概念指针类型的声明
char *a;char b = "B";a = &b;// print aB
间接访问操作符
通过一个指针访问它所指向的地址的过程称为间接访问(indirection),或解引用指针(dereferencing the pointer)。
用于执行间接访问的操作符就是单目操作符* ,
单目操作符* 也有叫 间接运算符* 。
间接引用过程图:
图1
图2
指针类型的长度
口 = 1bit ;
指针类型的长度 = 4字节,
【口口口口 口口口口】
【口口口口 口口口口】
【口口口口 口口口口】
【口口口口 口口口口】
了解即可 。
Why do I need to transfer the length?
因为在C语言中,数组作为参数的时候,就是一个指针。
因此,在函数内,是不能通过sizeof( )之类的函数得到这个指针所指字符串的长度的,得到的只是指针变量的长度。必须也得将长度传输过去。
二维指针
以此类推,还有三维、四维指针;
就是指向指针的指针。
问题:二维指针在哪里能用到?
TODO
const修饰的指针
直接看: https://blog.51cto.com/waleon/5670923 (看 1. const属性 章节)
总结就是, 使用const修饰指针变量,这个指针地址不能改变了,但是,指针指向的内存地址,这个地址存储的数据是可以改变的。
指针运算
先思考,指针运算都用在哪里?
- 指针++,这种用在链式数组,可以向后读取数据。
example :
有一段字符串 ” ajskldjfklajdfl ” ,自定义一个函数统计出其中j字符在该字符串中所出现的次数。(使用指针的方式实现)
int Count(chat* p){ int count = 0; for(int i=0; *(p+i)!='\0'; i++){ if (*(p+i) == 'j'){ count++; }}return count;}void main(){char str[] = "ajskldjfklajdfl"printf("有几个j : %d", Count(str));}
为什么需要指针?
早期的电子设备是不需要指针的,当时的设备的内存极小,哪怕是到了现在,一枚ESP32-C3单片机的内存也才内置不过400 KB SRAM。当时的程序员们可以使用汇编直接控制寄存器,可是后来内存越来越大,直接控制寄存器就变得越来越麻烦,于是封装了“指针”这个抽象的概念用以进行间接寻址。
指针让程序员得以从硬件中解放出来,却没有剥夺程序员们灵活自由控制内存的权力。自由控制内存权利这个东西,看给谁用,给优秀的人,就是锋利的工具,能锦上添花,给愚蠢的人,就会干出蠢事且危险失控的事。比如:
- 用指针在堆内申请内存却忘了释放,造成内存泄漏;
- 访问野指针造成预料之外的行为;访问空指针导致程序报错;等等
指针能提低内存消耗,高效率传输的案例:
假设你从内存中一次性读取了一个1GB的文件,哪么存放这些数据的变量也会消耗1GB的内存。姑且不论申请堆区内存和读取文件的部分,假如你需要写一个函数处理这些文件,如果不用指针的话,调用函数时会在内存中再拷贝一份数据成为函数内的临时变量,而这份拷贝同样会消耗1GB内存。如此庞大的内存消耗,作为存放在栈区的临时变量无疑会塞满栈区,并且因为塞不下而导致程序出错;哪怕没有出错,这么庞大的资源消耗也表明这是一个毫无优化的程序,用户体验极差。
虽然实际工程中会通过分块读写文件以降低资源消耗,但不可否认,没了指针哪怕分块读写都会消耗双倍内存。使用指针作为函数参数,可以让函数直接操作指针地址存放的数据,这种参数传递方式会在第三节进行介绍,名为指针传递
。
函数指针
函数指针也可以称为回调函数、指针函数…,那么是什么函数指针?
reference:
什么是函数指针
https://333rd.net/posts/read/什么是函数指针/
Reference
【C语言指针】三分钟理解C指针【动画展示】
https://www.bilibili.com/video/BV1YB4y1D7cS/?spm_id_from=333.337.search-card.all.click&vd_source=8b3d9b9c8dc3d45e894bef954677559d
【指针的秘密】这可能是最好懂的C语言指针讲解
https://www.bilibili.com/video/BV1V44y1Y7JS/?spm_id_from=333.337.search-card.all.click&vd_source=8b3d9b9c8dc3d45e894bef954677559d
指针的前世今生
https://333rd.net/posts/read/指针的前世今生/#12-内存的本质
C 指针 | 从底层原理到花式技巧(图文详解)
https://blog.51cto.com/waleon/5670923
一个软件开发者(安全方向)的公众号。 Mysticbinary
Github:https://github.com/Mysticbinary
既然看到了这里,君何不畅谈一番?