1.指针变量和地址
其实在代码中定义一个局部变量,就是向内存中申请一块空间,这块空间的名称就叫做地址
而 地址==指针
1.1.指针的两个操作 & 和 *
&:取地址操作符
表示将a的地址取出来给p
*:解引用操作符
取出p指向地址中的值
int* p = &a;
int:在说明指向的对象是int
*:说明p是指针变量
1.2.指针变量的大小
也就是:
char*指向字符的指针
short*指向短整型的指针
int*指向整型的指针
float*指向单精度浮点型的指针
void*无具体类型的指针
的大小
2.指针变量类型意义
2.1.解引用
下面创建了一个int类型的a
第一次解引用是用int*来接受
第二次解引用是用char*来接受
但是对解引用的值进行改变的时候,int*可以改变4字节没问题,但是char*只能改变一个字节
2.2.决定了指针的步长
也是用char*和int*进行对比
p地址+1的时候加的是int的4个字节
q地址+1的时候加的是的char的1个字节
结论:
指针类型决定了指针的步长,就是向前/向后走一步走多大距离
type* p;
p+i 是跳过i个type类型的数据相当于跳过了i*sizeof(type)个字节
2.3.void*

3.count修饰
const本身的的作用是将可改变的变量修饰为不可改变的常变量,
但是,const修饰以后还是一个变量
const修饰指针
分为两种
1.const int * p:地址指向的内容本身不可以被修改
2.int * const p:地址本身不能被修改
4.指针之间的运算


5.野指针
5.1.野指针的形成
1. 指针未初始化
2. 指针越界访问

5.2.野指针的规避
1.初始化为NULL



6.assert断言

7.指针的使用
1.使用指针完成个strlen的功能
strlen的功能是求字符串⻓度,统计的是字符串中 \0 之前的字符的个数。
自我实现

8.指针与数组
8.1.数组名的理解
都知道数组名就代表数组的首元素地址,
但是
+1操作;

8.2.一维数组传参的本质
int arr[]
这种形式本质上等同于 int *arr
,也就是它实际上是一个指向 int
类型的指针,并非真正的数组。
当你把数组作为参数传递给函数时,传递的其实是数组首元素的地址,而非整个数组的副本。
8.3数组指针
数组指针就是指向数组的指针,也是一种指针变量,用于存放数组的地址
8.4.二维数组传参本质
假设存放的是int
二维数组传参的本质是传递数组首元素的地址,但是首元素是一个int整形
二维数组传参的本质是传递数组首元素的地址,但是首元素是一个int类型的一维数组
int (*arr)[4]
是一个指向包含 4 个int
元素的一维数组的指针。
9.二级指针
10.字符指针变量
指向字符串常量 和 指向字符数组进行比较
1. 指向字符串常量
str
是一个字符指针变量,它指向了字符串常量 "akjfd"的首地址
字符串常量存储在只读内存区域,不能通过指针去修改它的值。如果尝试修改,会导致未定义行为
2.指向字符数组
指向了字符数组 arr
的首字符地址。与字符串常量不同,
字符数组存储在可读写的内存区域,可以通过指针修改数组中的字符

11.函数指针变量
函数指针变量的定义:
函数指针变量的使用:
x和y加上和不写上都是可以的
11.1.typedef关键字
函数指针这个变量名字过于冗余,所以使用typedef关键字对函数指针这个变量名字进行一个取别名的操作
语法格式:
实际调用: