1,指针是什么?
内存空间被划分为一个个内存单元,取一个字节为一个内存单元。为方便管理,每个内存单元被进行了编号——地址——指针。
内存单元编号的产生:
对于32位机器,假设有32根地址线,那么通电后每根地址线会产生一个电信号正电 / 负电,电信号转化为数字信号后,即32个1 / 0组成的2进制序列。(2的32次方个地址)
注意:地址以16进制进行表示,即32位平台上表示地址为0x15FF4576(8个16进制位)
指针变量:
用于存放内存单元的地址(指针)的一种变量
实例:
注意:存放在指针变量中的值都将被当成地址来处理
指针的双重含义
指针通常指的是指针变量,同时也可以指内存单元的地址。区别在于前者存放于内存中,占据一定的内存空间;后者仅仅是指内存单元的编号,不占据内存空间。
指针变量的大小
内存空间编号产生时,在32位平台产生32个2进制序列,即指针变量占据4个字节;在64位平台产生64个2进制序列,即指针变量占据8个字节
2,指针和指针类型
不同类型的指针在32位 / 64位平台上所占据的内存大小是相同的(4bity / 8bity)。所以在一个平台上,任何变量的地址都可以存放在不同类型的指针中。
指针类型的意义
1,指针类型决定了指针解引用的权限有多大(操作的字节数)
案例:
2,指针类型决定了指针+ - 整数时,指针向前或者向后走一步有多大(距离)
案例:
3,野指针
概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
野指针成因
1,指针未初始化
解释:局部变量未初始化,默认随机值。对应局部指针变量指向地址空间随机地址(可能指向不属于当前程序的地址区域),导致非法访问内存。
2,越界访问
pi指针指向的范围超出arr数组范围,导致非法访问内存
3,指针指向的空间释放
如何避免野指针
1,初始化变量(指针可初始化为空值NULL,空值指针不可使用!)
2,小心指针越界(C语言本身不会检查越界行为!)
3,指针指向空间释放时及时置NULL
4,指针使用之前检查有效性(判断是否NULL)
4,指针运算
指针 +- 整数
指针 - 指针
指针的关系运算
下面的代码包含<指针 + 整数>和<指针的关系运算>:
指针 - 指针:返回指针之间的元素个数
指针的关系运算
对比下面两种数组元素从后往前赋值的代码
前者指针从&arr[5]开始,最终指针停在&arr[0]上。(符合标准)
后者指针从&arr[4]开始,最终指针停在&arr[-1]上。(不符合标准)
标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
5,指针和数组
数组名是数组首元素的地址
对于下标引用操作符 [] 来说,编译器的处理过程本质上是对指针进行处理
例如:对整型数组arr取出第三个元素,即arr[2]
引申:通过进一步处理,arr[2]可转化为2[arr]
6,二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针。
1, 二级指针ppi可以通过解引用,找到pa,*ppi实际上就是访问pi
2,**ppi先通过*ppi找到pi,然后对pi进行解引用:*pi,找到a