指针初阶版
虽说是初阶版,但关于指针的东西基本都有,后续会有对指针的更深切入,跟着我由浅到深的探索指针的奥秘
一、什么是指针?
指针就是地址,口语中的指针通常指的是指针变量
指针的大小在32位平台是4个字节,在64位平台是8个字节
二、指针和指针类型
指针类型的作用:
- 指针类型可以决定指针在解引用时可以访问多少个字节(指针的权限)
int* 的指针解引用访问4个字节
char* 1
short* 2
float* 4
double* 8
- 指针类型决定指针 +/- 操作时的步长
整型指针+1 跳过4个字节
字符型指针+1 跳过一个字节
三、野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没限制的)
如何避免野指针:
- 指针初始化
指针未初始化时,实际这个指针变量里存放的值是系统给的随机值,你可以通过解引用的方式去访问这个随机值表示的内存里的东西,甚至可以修改,但是这块地址是自由的,可以被其他数据使用,当这块地址已经被使用时,你在操作这个为初始的指针是很危险的,很容易修改这块地址里的内容。
因此,创建指针变量时,要给指针初始化,或着置空(int * p = NULL) - 小心指针越界
访问数组时避免指针越界 - 指针指向的空间释放后,及时置NULL
- 避免返回局部变量的地址
返回局部变量地址时,实际上这个局部变量所用的这块内存的使用权已经还给操作系统了,你再访问这个地址时,也是很危险的,原理与指针初始化的相同 - 指针使用时判断有效性
四、指针的运算
4.1 指针 + / -
上文中指针类型决定+/- 操作时的步长已经讲解
4.2 指针 - 指针
指针 - 指针得到的数值的绝对值,是指针和指针之间的元素个数
前提条件:指针与指针指向的是同一块内存空间
4.3指针的关系运算
指针和指针是可以进行比大小
#define N 5
int arr[N] = { 0 };
int* p = NULL;
for(p = arr[N-1]; p >= &arr[0]; p--)
{
*p = 0;
}
for(p = arr[N]; p > &arr[0]; )
{
*--p = 0;
}
两段代码都是为了给这个数组赋值,都可以运行,注意看指针的初始和结束位置
- 第二段代码开始,指针p指向数组末尾的位置,它与&arr[0]比较大小
- 第一段代码,在出循环前,此时指针p已经指向了数组首元素的前一个位置,然后进行比大小,这是不被允许的
C语言规定:
- 允许数组元素的指针和数组最后一个元素后面的那个内存位置的指针比较
- 但是不允许与指向第一个元素前面的内存位置的指针比较
五、指针和数组
指针和数组之间有什么关系呢?
- 指针变量就是指针变量,不是数组,指针变量的大小是4/8个字节,是专门用来存放地址的
- 数组就是数组,不是指针,数组是一块连续的空间,可以存放一个或多个相同类型的数据
联系:
- 数组中,数组名其实是数组首元素地址,数组名 = = 地址 = = 指针
- 当我们知道数组名是首元素地址时,数组又是连续存放的,所以通过指针就可以对数组进行访问
六、二级指针
int a = 10;
int* p = &a; p是一级指针变量,指针变量也是变量,
变量是要在内存中开辟空间的,是变量就有地址
int** pp = &p; pp就是二级指针变量,
二级指针变量就是来存放一级指针变量的地址
*(*pp) = 100; //把a的值改为100