什么是指针
专门用来储存地址的变量,也可以说只要存放在中的就是地址
指针使用
* 解引用符号,对指针储存的地址进行访问
指针类型
指针类型决定了指针进行加减运算时跳过多少个字节
int*,加一跳过4个字节,也就是int类型的大小,char*跳过1个字节,也即是char类型的大小
所以指针加减跳过的大小等于该类型的大小
void*
void*类型的指针可以用来接收所有类型的指针,但要注意不能直接进行指针的加减和解应用
const
用const修饰指针变量int*p = &a
当const修饰p时
int* const p = &a,表示p储存的地址不能再被改变
当const修饰*p时
int const *p = &a,表示a的值不能再改变,比如a =2,在被const修饰时a就不能等于其他数
野指针
没有明确指向的指针(随机的,不可取的)
出现原因
1,没有初始化
2,数组越界
3,指向的空间已经释放
assert断言
assert.h头文件定义了宏assert(),用于在运行时确保程序符合指定条件,如果不符合,就报错
终止运行,这个宏被称为断言
如assert(p != NULL), 验证p是否等于NULL,如果不为NULL表达式为真程序正常运行
如果为p = NULL为假,会终止程序并爆出错误的文件名和行号,还有没有通过的表达
当你觉得程序没有错误不需要assert断言时,只需要在assert.h前加上#define NDEBUG
这样就关掉的assert断言
指针加减
而数组其实就是一串连续的地址,在进行访问时也就是对其地址进行解引用,数组名时首元素地址
地址-地址 = 俩地址之间的元素个数
arr[0] = *(arr + 0) ,arr[1] = *(arr + 1),
arr[5] = {1,2,3,4,5},&arr[4] - &arr[0] = 4
指针 +- 数字,arr[0] = *( arr + 0) ,arr[1] = *(arr + 1),arr是int*类型的指针,加一加一个指针的大小,也就刚好指向arr[1]的地址,通过向地址加上不同的数这样就可以实现数组的遍历。
所以一个循环打印数组也可以这样写
数组传参
数组传参的本质是传首元素地址,因为传给函数的形参是实参的一份临时拷贝,改变形参并不能
改变实参,通过将地址传过去在函数里通过地址去更改地址指向的值实现数组的初始化操作
二级指针
int* p = &a ,p就叫做一级指针,储存一级指针的指针就叫做二级指针,写作int** pp = &p
int* 的意思是p指向的p是一个int*的类型,*pp的意思是pp是一个指针变量
指针数组
存储地址的数组
具体的地址储存情况
可以用来实现二维数组存参
(arr+i)得到arr中储存的数组的地址,解引用得到数组arr[i],(*(arr +i) +j)得到数组的每一个元素的地址&arr[j],解引用的到对应的元素、
字符串指针
储存的是字符串的首元素地址,char* p这个是个常量字符串,常量字符串不能被修改所以一下代码是不能正常运行,f是个字符数组可以修改
数组指针变量
存放的是数组的地址,能够指向数组的指针变量,是指针
*p 得到数组arr的地址,+i 遍历arr数组
int(*p)[4] = &arr,*p的意思是这是个指针变量,int意思是这个指向的数组是int类型
[4]的意思这个数组大小为4
函数变量指针
存放函数地址的指针
p储存是的函数Add的地址,*p得到函数Add,(int,int)意思是传入的是俩个int类型的
变量,int意思是函数的放回值为int类型
函数指针数组
把函数的地址存入数组中,这个数组就叫做函数指针数组
计算器的实现
和储存其他元素的数组一样,Sub的地址储存在p[0],Add储存在p[1]
*p[2]的意思是函数指针变量,后面的括号和函数变量指针一样,是传入的元素的类型
qsort函数
qsort( arr , sz , sizeof(arr[0]) , sort_t ),arr是数组的首元素,sz是数组的元素个数,
sizeof(arr[0])是1个元素的大小,sort_t是自己写的,用来确定交换条件,
sort_t的返回值是int类型,p1 == p2时,返回0,p1>p2放回大于0,小于放回小于0
但返回值大于0时,p1和p2的值交换
qsort能排序各种数组,包括字符,字符排序是根据相对应的字符的ascll码值确定。