指针相关的总结:
1.指针数组:一个数组的元素都是指针类型的数据称为指针数组
定义一维数组的一般形式为:类型名* 数组名[数组长度];
例如:int* p[5];
由于[]优先级高,先跟p结合这就是一个数组的形式,然后再跟前面的‘*’结合,’*’表示此数组是指针类型的,每个数组元素都可以指向一个整型变量。
2.数组指针:一个指向数组的指针。
定义数组指针的一般形式:类型名 (*数组名)[数组的长度];
例如:int (*p)[5]
p先和*结合,说明p是一个指针变量,然后指向一个有着五个整型元素的数组,由于[]的优先级高于’*’所以要加个’()’保证p先和*结合。
3.函数指针:一个指向函数的指针。
定义函数指针的一般形式:类型名 (*指针变量名)(函数参数列表);
例如:int (*p)(int,int)
p是一个指针指向一个函数类型为整形的并且有两个整型参数的函数。函数名代表函数的起始地址,p存放的是函数的起始地址,函数名代表函数的起始地址,则指针指向的是该函数。
两个有趣的代码:
(*(void(*)())0)(); void(*signal(int,void(*)(int)))(int);
第一个代码的是把零强制转换成函数指针类型,再解引用
第二个代码可以用三点解释:
1.signal是个函数。
2.该函数有两个参数,第一个为int类型,第二个函数参数为函数指针,该指针指向的函数有一个整型参数,返回类型为void。
3.signal函数的返回类型为一个函数指针类型,该指针指向的函数有一个整形参数,返回类型为void。
使用typedef定义函数指针类型
typedef int (*PF)(int,int); PF pf;//此时,为指向某种类型函数的函数指针类型,而不是具体指针,用它可定义具体指针
//代码2就可以简化 typedef void (*pfun_t)(int); pfun_t signal(int,pfun_t);//pfunt为函数指针类型
函数指针的常见用途:函数指针作为函数的形参。
# include<stdio.h> # include<stdlib.h> int Max(int x, int y) { return x > y ? x : y; } int get_max(int x, int y, int(*Max)(int, int)) { return Max(x, y); } int main() { int x = 0; int y = 0; printf("请输入两个数\n"); scanf("%d%d", &x, &y); int max = get_max(x, y, Max); printf("max=%d\n", max); system("pause"); return 0; }
4.函数指针数组:把函数地址存放在一个数组里面,那这个数组就是函数指针数组。
定义函数指针数组的一般形式:类型名 (*数组名[])(函数参数列表)
例如:int (*p[])(int,int)
p先和[]结合 说明p是一个数组,存放的是int(*)(int,int)函数的地址。
函数指针数组的用途:转移表。
转移表:就是一个函数指针数组。
创建一个转移表需要两个步骤。首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这些函数的原型出现在这个数组的声明之前。
为什么要使用转移表???
如果要实现一个简单的计算器:
switch(operation) { case ADD: result=add(a,b);break; case SUB: result=sub(a,b);break; case MUL: result=mul(a,b);break; case DIV: result=div(a,b);break; ..... }
如果计算器的功能要变得更复杂,要进行的状态的判断会有很多,语句也就会很长。但是使用转移表将具体的数值操作与选择操作的代码分开将会提高代码的可读性。
int (*p[5])(int x, int y)={0,ADD,SUB,MUL,DIV};
初始化列表中各个函数名的正确顺序取决于程序中用于表示每个操作符的整型代码。
回调函数:我们把一个函数指针作为参数传递给函数,然后函数“回调”函数指针指向的用户函数,这样的函数就称为回调函数(callback function)。
回调函数不是由函数的实现方直接调用,而是在特定的事件或者条件发生时由另一方调用的,用于对该事件或者条件响应。
使用回调函数实现模拟qsort:
#include<stdio.h> #include<stdlib.h> int int_cmp(const void *p1, const void *p2) { return (*(int *)p1 > *(int *)p2); } void _swap(void *p1, void *p2, int size) { int i = 0; int j = 0; for (; i<size; i++) { char tmp = *((char *)p1 + i); *((char *)p1 + i) = *((char *)p2 + i); *((char *)p2 + i) = tmp; } } void buttle(void *base, int count, int size, int(*cmp)(void *, void *)) { int i = 0; int j = 0; for (; i<count - 1; i++) { for (; j<count - i - 1; j++) { if (cmp((char *)base + j*size, (char *)base + (j + 1)*size)>0) { _swap((char *)base + j*size, (char *)base + (j + 1)*size, size); } } } } int main() { int arr[] = { 1, 2, 4, 3, 5, 8, 6 }; int i = 1; buttle(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); for(i = 0;i < sizeof(arr) / sizeof(arr[0]); i++) { printf("%d ", arr[i]); } system("pause"); return 0; }
5.函数指针数组的指针:一个指向函数指针数组的指针。
定义函数指针数组的指针的一般形式:类型名(*(*数组名[]))(函数参数列表);
例如:int (*(*p[]))(int, int)