一级指针
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节(32位平台/64位平台)。
- 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
二级指针
二级指针本质上是一个一级指针 , 只不过这个一级指针指向的内容也是一个一级指针
指针和数组
指针和数组在C语言中经常被混用,但二者有本质区别:
- 数组是自带内存空间的,往往是把原来的数据复制到新申请的内存空间
- 指针变量自身的内存空间就是固定的4个字节 , 不论指向什么内容 , 这4个字节只保存对应的内存空间的地址上 , 不涉及数据拷贝过程
指针数组&数组指针
int *arr[ ] :指针数组,是一个数组,每个元素都是一个指针
int (*p)[ ] :数组指针,是一个指针,指向了一个数组(的首地址)
可以用typedef来帮助理解数组指针:
typedef int(Point)[4] //(类型叫int[4])
Point* p=int (*p)[4]
二者没有任何联系,只是因为名字相似经常会一起出现,需要明确区分开
**注意:**在某些条件下数组指针可以转换成二级指针 , 二维数组不能转成二级指针
二维数组传参 , 函数形参设计只能省略arr[ ][ ]
中的第一个[ ]
, 的元素即arr[ ][i]
, 对于二维数组,可以不知道有多少行,但是要知道每一行是几个元素(每个数组是几个元素),方便计算
数组元素与解引用:
char* p="hehe"
p[0]=*(p+0)
int (*arr[5])[5]
指针数组,每个元素又是一个指针数组
函数指针
用途:转移表(表驱动方式)
1.void (*pfunc1)()=Func
pfunc1是函数指针 , 指向Func , 类型为 void(*)()
2.int (*pfunc2)(int x,int y)=add
pfunc2指向Add , 类型为int(*)(int x,int y)
函数指针也可以解引用,解引用得到的不是数据而是一个函数,这个函数可以调用 , 使用()
函数调用操作符来进行调用
对于函数指针来说,调用函数是最核心的使命 , 即使不进行解引 , 也能进行函数调用
3.void ( * signl ( int , void(*)(int) ) )
signl是一个函数,参数有两个;第一个参数是int
, 第二个是函数指针
这个函数指针参数是int
,返回值是void
, signl函数返回值是函数指针
4.typedef void(*h)(int); h signl(int,h);
此时定义了一个一个类型h , 这个类型是函数指针类型 , 参数为int ,返回值是void的函数指针(简化函数指针)
回调函数
普通的函数调用时机由程序员自己决定,毁掉函数的调用时机由操作系统或代码框架来决定
典型的例子有回调版的冒泡排序:
#include <stdio.h>
void Swap(int* x,int * y){
int tmp = *x;
*x = *y;
*y = tmp;
}
typedef int(*Cmp)(int,int);
int BulleSort(int arr[],int size,Cmp cmp){
int bound = 0;
for (; bound <size ; ++bound) {
for (int cur = size-1; cur > bound ; -- cur) {
if(cmp(arr[cur-1],arr[cur])){
Swap(&arr[cur-1],&arr[cur]);
}
}
}
}
int Less(int x,int y){
//升序
if(x < y){
return 0;
}
return 1;
}
int Greater(int x,int y){
//降序
if(x > y){
return 0;
}
return 1;
}
int main(){
int arr1[]={
9,5,2,7};
int arr2[]={
9,5,2,7};
int size1= sizeof(arr1)/ sizeof(arr1[0]);
BulleSort(arr1,size1,Less);
for (int i = 0;