1 指针是一种数据类型
1.1 指针变量
指针是一种数据类型,占用内存空间,用来保存内存地址。
1.2 野指针和空指针
1.2.1 空指针
标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针为NULL,可以给它赋值一个零值。为了测试一个指针百年来那个是否为NULL,你可以将它与零值进行比较。
对指针解引用操作可以获得它所指向的值。但从定义上看,NULL指针并未指向任何东西,因为对一个NULL指针因引用是一个非法的操作,在解引用之前,必须确保它不是一个NULL指针。
如果对一个NULL指针间接访问会发生什么呢?结果因编译器而异。
不允许向NULL和非法地址拷贝内存:
1.2.2 野指针
在使用指针时,要避免野指针的出现:
野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。
什么情况下回导致野指针?
- 指针变量未初始化
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。 - 指针释放后未置空
有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。 - 指针操作超越变量作用域
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
操作野指针是非常危险的操作,应该规避野指针的出现:
- 初始化时置 NULL
指针变量一定要初始化为NULL,因为任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的。 - 释放时置 NULL
当指针p指向的内存空间释放时,没有设置指针p的值为NULL。delete和free只是把内存空间释放了,但是并没有将指针p的值赋为NULL。通常判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。
1.3 间接访问操作符
通过一个指针访问它所指向的地址的过程叫做间接访问,或者叫解引用指针,这个用于执行间接访问的操作符是*。
注意:对一个int类型指针解引用会产生一个整型值,类似地,对一个float指针解引用会产生了一个float类型的值。
- 在指针声明时,* 号表示所声明的变量为指针
- 在指针使用时,* 号表示操作指针所指向的内存空间
- * 相当通过地址(指针变量的值)找到指针指向的内存,再操作内存
- * 放在等号的左边赋值(给内存赋值,写内存)
- * 放在等号的右边取值(从内存中取值,读内存)
1.4 指针的步长
指针是一种数据类型,是指它指向的内存空间的数据类型。指针所指向的内存空间决定了指针的步长。指针的步长指的是,当指针+1时候,移动多少字节单位。
思考如下问题:
2 指针的意义_间接赋值
2.1 间接赋值的三大条件
通过指针间接赋值成立的三大条件:
- 2个变量(一个普通变量一个指针变量、或者一个实参一个形参)
- 建立关系
- 通过 * 操作指针指向的内存
2.2 如何定义合适的指针变量
2.3 间接赋值:从0级指针到1级指针
2.4 间接赋值:从1级指针到2级指针
2.4 间接赋值的推论
- 用1级指针形参,去间接修改了0级指针(实参)的值。
- 用2级指针形参,去间接修改了1级指针(实参)的值。
- 用3级指针形参,去间接修改了2级指针(实参)的值。
- 用n级指针形参,去间接修改了n-1级指针(实参)的值。
3 指针做函数参数
指针做函数参数,具备输入和输出特性:
- 输入:主调函数分配内存
- 输出:被调用函数分配内存
3.1 输入特性
3.2 输出特性
4 字符串指针强化
4.1 字符串指针做函数参数
4.1.1 字符串基本操作
八进制和十六进制转义字符:
在C中有两种特殊的字符,八进制转义字符和十六进制转义字符,八进制字符的一般形式是’\ddd’,d是0-7的数字。十六进制字符的一般形式是’\xhh’,h是0-9或A-F内的一个。八进制字符和十六进制字符表示的是字符的ASCII码对应的数值。
比如 :
- ‘\063’表示的是字符’3’,因为’3’的ASCII码是30(十六进制),48(十进制),63(八进制)。
- ‘\x41’表示的是字符’A’,因为’A’的ASCII码是41(十六进制),65(十进制),101(八进制)。
4.1.2 字符串拷贝功能实现
4.1.3 字符串反转模型
4.2字符串的格式化
4.2.1 sprintf
4.2.2 sscanf
格式 | 作用 |
%*s或%*d | 跳过数据 |
%[width]s | 读指定宽度的数据 |
%[a-z] | 匹配a到z中任意字符(尽可能多的匹配) |
%[aBc] | 匹配a、B、c中一员,贪婪性 |
%[^a] | 匹配非a的任意字符,贪婪性 |
%[^a-z] | 表示读取除a-z以外的所有字符 |
5 一级指针易错点
5.1 越界
5.2 指针叠加会不断改变指针指向
5.3 返回局部变量地址
5.4 同一块内存释放多次(不可以释放野指针)
6 const使用