指针进阶
数组与指针
指针数组与数组指针
数组:int arr[10];
表示arr为有10个元素的数组,每个元素的类型为int
指针数组:int* arr[10];
表示arr为有10个元素的数组,每个元素的类型为int*,即指针数组
二级指针
概念:存放一级指针的地址的指针变量
注:指针变量类型的理解与区分:
int*- 指向*前的int类型的指针变量int**- 指向*前的int*类型的指针变量
函数指针、函数指针数组
函数指针
概念:指向函数的指针(存放函数地址的指针)
定义方法:
int(*pfunction)(int, int) = &function;(类型为int (*)(int, int))函数指针数组
概念:存放函数指针的数组
定义方法:
int(*arr[10])();(数组元素的类型为int (*)())指向函数指针数组的指针
这种就属于嵌套了上面的概念,其他嵌套也一样,仔细分析可以知道这是存放函数指针数组地址的指针
注:试分析:
void (*function(int, void(*)(int)))(int);的含义它实际上等价于下面的代码,在实际开发中,尽量不要使用上面复杂的写法
typedef void (*pfunction)(int); // 定义pfunction类型 pfunction function(int, pfunction); // 声明了function函数,返回值和参数都是函数指针
指针的左右法则
步骤
- 找到核心标识符:从声明中最内侧的变量名或函数名开始分析(这是解析的起点)
- 先右后左解析
- 先看标识符右边的符号(如
[]表示数组,()表示函数) - 再看标识符左边的符号(如
*表示指针) - 重复 “右→左” 的顺序,逐步向外层扩展,直到解析完整个声明
- 先看标识符右边的符号(如
- 遇到括号优先处理:括号会改变解析顺序,先解析括号内的内容
示例解析
以复杂声明
int *(*func[10])(char *)为例,用右左法则拆解找到核心标识符 func 声明的主体是
func,从它开始解析先看右边:[10]
func右边是[10],表示func是一个 “包含 10 个元素的数组”再看左边:* 数组左边有
*,表示这个数组的元素是 “指针”(即func是一个 “指针数组”)继续向外,看右边的 (char *) 指针数组外侧有
(char *),表示这些指针指向 “函数”(因为函数声明用()表示),且该函数接受一个char *类型的参数最后看左边的 int * 函数左边是
int *,表示这个函数的返回值是 “int *类型的指针”最终结论
int *(*func[10])(char *)表示:func是一个包含 10 个元素的数组,数组中的每个元素都是函数指针,这些指针指向的函数接受 char * 类型参数,并返回 int * 类型指针
指针传参
一维数组传参
// 传递实参int arr[10];的方法 void test(int arr[10]) {} void test(int arr[]) {} void test(int* arr) {} // 传递实参int* arr[20];的方法 void test(int* arr[20]) {} void test(int* arr[]) {} void test(int** arr) {}二维数组传参
// 传递实参int arr[3][5];的方法 void test(int arr[3][5]) {} void test(int arr[][5]) {} void test(int (*arr)[5]) {}指针传参思考
Q:思考:当函数的形参为一级指针时,可以接收的实参有哪些?
A:一级指针、一维数组
Q:思考:当函数的形参为二级指针时,可以接收的实参有哪些?
A:二级指针、一级指针数组
回调函数
概念
一个通过函数指针调用的函数。如果把函数的指针作为参数传递给另一个函数,当这个指针被用来调用其指向的函数时,我们就说这是回调函数
注:
- 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另一方调用的,用于对于该事件或条件的响应
- 这种机制,我们称之为“回调函数机制”
实例
// 使用回调函数编写冒泡排序函数 void bubble_sort(void* ptr, size_t count, size_t size, int (*cmp)(const void* e1, const void* e2)) { int num = 0, judge = 1; for (; num < count - 1 && judge; num++) { int i = 0; judge = 0; // 标志位:假设已经有序 for (i = 0; i < count - 1 - num; i++) { if (cmp((char*) ptr + size * i, (char*) ptr + size * (i + 1)) > 0) { int j = 0; judge = 1; for (j = 0; j < size; j++) { *((char*) ptr + i * size + j) = *((char*) ptr + i * size + j) ^ *((char*) ptr + (i + 1) * size + j); *((char*) ptr + (i + 1) * size + j) = *((char*) ptr + i * size + j) ^ *((char*) ptr + (i + 1) * size + j); *((char*) ptr + i * size + j) = *((char*) ptr + i * size + j) ^ *((char*) ptr + (i + 1) * size + j); } } } } }