1.指针是什么
为了说清楚什么是指针,我们先理解一下内存和地址
先打个比方在我们生活中的案例:
假设有一栋楼,把你放在楼里让你的同学去去找你,但是没有编号一个一个去找你这样效率会很低
如果我们给房间编上编号,就能提高效率,快速找到房间
生活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也成为地址。c语言中给地址起了新的名字叫:指针。
所以我们可以理解为:内存单元的编号==地址==指针
2.指针变量和地址
取地址操作符(&)
在c语言中创建变量其实就是向内存申请空间,比如
上述代码就是创建了整形变量a,内存中申请4个字节,用于存放整数10,其中每个字节都有地址,上图中的4个字节的的地址分别时
那么我们该如何得到a的地址呢?
就要学习一个新的操作符(&)-取地址操作符
屏幕上会打印出:006FFD70
&a取出的是a所占4个字节中地址较小的地址
虽然整形变量占用4个字节,我们只要知道了一个字节地址,顺藤摸瓜访问到第四个字节数据也是可以的。
2指针变量解引用
2.1指针变量
我们知道存放地址的变量,它用来指向另一个对向(如变量,数组,函数等)。那么我们该怎样定义和使用指针变量呢?
比如:
指针变量也是一种变量,这种变量就是用来存放地址的,存放指针变量里的值都会理解为地址。
2.2如何拆解指针类型
我们看到pa的类型是int*,我们该如何理解指针的类型呢?
int a= 10;
int* pa = &a;
这里pa左边写的是int*,*说明pa是指针变量, 而前面的int*说明pa指向的是整(int)的类型对象。
3解引用操作符
我们保存一个地址是要拿来使用的,c语言中就规定了一个操作符叫解引用操作符(*)
*pa的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是变量,所以*pa=0,这个操作符就是把a改成0。
3.1指针变量大小
![](https://img-blog.csdnimg.cn/direct/8c80ae32ea2948f38f3e6f1e16c328c5.png)
![](https://img-blog.csdnimg.cn/direct/f96d80de3120438bbd20b2779fd8afb8.png)
3.2指针的+-整数
先看一下代码观察变化
不难看出,char*类型的指针变量+1跳过1个字节,int*类型的指针变量+1跳过4个字节。
总结:指针的类型决定了指针向前或向后走一步的距离。
3.3 void*指针
在指针类型中有一种特殊类型的指针是void*类型的指针,可以理解为没有具体类型的指针你,可以接收任意类型的地址。但是也有局限性,void*类型的指针不能直接进行至今的+-整数和解引用的运算。
运行上面代码编译器给出了一个警告从int*到char*的类型不兼容,而使用void*的类型编译器就不会有这样的问题。
具体使用方法深入理解指针4会细讲~
4const修饰指针
变量是可以修改的,我们把变量地址交给一个指针变量,通过指针变量也可以修改这个变量。
那么有什么方法可以限制不被修改呢?接下来我们就来说说const的作用。
上述代码中n是不能被修改的,n的本质是变量,但是在被const修饰后就加上了限制,
如果进行修改编译器就会报错。
但是如果我们绕过n,使用n的地址,去修改就能做到了。
这里我们可以看到确实被修改了,这样就打破了const修饰的限制,所以应该让P拿到n的地址也不能修改n,那么接下来我们该怎么做呢?
4.1const修饰指变量
一般来说const指针变量,可以放在*的左边,也可以放在*的右边,意义是不一样的。
int * p;//没有const修饰?
int const * p;//const 放在*的左边做修饰
int * const p;//const 放在*的右边做修饰
我们用代码来分析一下
分析可知:
5.指针的运算
指针的基本运算有三种,分别是:
- 指针+-整数
- 指针-指针
- 指针的关系运算
5.1指针+-整数
因为数组指针在内存中是连续存放的,只要知道第一个元素地址,就能顺藤摸瓜找到后面的元素。
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
打印的p+i就是指针+整数
5.2指针-指针
s就是数组的首元素地址P1指向的,p求的是到\0之前的长度图中p2指向。
5.3指针的关系运算
指针的关系运算就是指针的大小比较
6.1野指针成因
1.指针未初始化
2.指针越界访问
3.指针指向的空间释放
7 如何规避野指针
如果明确知道指针指向哪里就直接给指针赋值,如果不知道就给指针赋值NULL,NULL是语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写会报错。
7.1指针初始化
代码如下:
8.assert断言
assert.h头文件定义了宏assert(),用在确保运行时程序符不符合条件,不符合就报错,终止运行
这个宏被称为“断言”。
assert(p != NULL);
示例:
编译器会显示报错,显示断言失败
8.1指针的使用和传址调用
8.1 strlen的功能是求字符串长度,统计的是字符串\0 之前的字符个数。
函数原型:
1.函数参数为--const char*str:字符指针
2.返回值的类型--size_t:无符号整数(unsigned int)
参数str接收⼀个字符串的起始地址,然后开始统计字符串中 \0 之前的字符个数,最终返回⻓度。
strlen函数从字符首地址开始遍历,以'\0'为结束标志,然后将计算长度返回,计算长度不包括'\0'
代码如下: