在介绍指针定义之前,首先声明一些概念:
指针和数组无关:1.指针和数组是两种不同的类型。2.数组名不能整体赋值,数组名不能作为左值。
数组名单独使用时代表整个数组,数组名在被取地址时,代表整个数组的地址。
下来,我来介绍一些常见的指针名词:
指针数组:是数组,是一个存放指针的数组。比如:int *arr[10].
数组指针:是指针,有能力指向一个数组。比如:int (*p)[10];//注意:[]的优先级要高于*号,所以必须加上()来保证p先和*结合。
函数指针:是指针,有能力指向一个函数,既可以通过指针调用函数,亦可通过函数名直接表示。比如:int (*a)(int x,int y)。
函数指针数组:是数组,这个数组中的元素就是我们前面所提到的函数指针。比如:int (*parr1[10])()。
指向函数指针的数组的指针:是指针,指针指向一个数组,数组的元素都是函数指针。比如:void(*(*ppfunarr)[10](const char*).
看完了文字介绍之后,我们来通过代码对此分析:
#include <stdio.h> #include <stdlib.h> #include<windows.h> char *fun(char *p1, char *p2) { int i = 0; i = strcmp(p1, p2); if (0 == i) { return p1; } else { return p2; } } char *fun1(char *p) { printf("%s\n", p); return p; } char *fun2(char *p) { printf("%s\n", p); return p; } char *fun3(char *p) { printf("%s\n", p); return p; } int main() { int *arr[5];//指针数组 int (*pArr)[5] = &arr; //数组指针, //它是一个指针,指针有能力指向一个数组 //数组有5个元素,每个元素是一个整形指针 char *(*pf)(char *p1, char *p2); pf = &fun; (*pf)("aa", "bb"); //pf是一个函数指针; //该指针指向一个函数; //指向的函数参数为char*,char*类型,返回值类型为char *; char *(*a[3])(char *p); //a是一个函数指针数组; //该数组有三个元素,为函数指针; //该指针指向函数,函数参数为char *类型,返回值为char*; char *(*(*pe)[3])(char *p); //指向函数指针数组的指针; //是指针,指向函数指针数组; //该数组有三个元素,为函数指针; //该指针指向函数,函数参数为char *类型,返回值为char*; pe = &a; a[0] = fun1; a[1] = &fun2; a[2] = &fun3; pe[0][0]("fun1"); pe[0][1]("fun2"); pe[0][2]("fun3"); system("pause"); return 0; }
通过以上学习,我们对概念都有了一些了解,接下我们通过两个代码对自己做一点小测试吧:
void(*signal(int, void(*)(int)))(int); //是一个函数声明,signal是一个函数, //参数为int类型和函数指针类型,返回值为函数指针类型 代码也可简化如下: typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);
是不是感觉上个例子不够刺激,接下来我们再来看个例子吧:
(*(void(*)())0)() //void(*)(),这是一个函数指针类型,这个函数没有参数,没有返回值 //(void(*)()0),这是将0强制转换为函数指针类型,0是一个地址,也就是说一个函数存在首地址为0一段区域内。 //(*(void(*)()0),这是取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数。 //(*(void(*)())0)(),这是函数调用。
通过以上分享,希望能帮到大家!
对于函数指针,后面还有一些深度理解:https://blog.csdn.net/cdatreides/article/details/80427054