C语言指针进阶(2)

时间:2021-02-15 00:57:08

一、函数指针

函数指针也只是一个普普通通的指针,不过它指向的对象变成了函数,或者说它存储的是函数的地址

我们都知道,int *pp=&a;,我们把指针(*p)去掉后,剩下的int就是指针所指向对象的类型,而在函数指针中,函数的类型由它们的返回类型以及函数参数决定,

1.1开胃小菜

函数名和&函数名是等价的,它们表示的都是函数的地址,验证如下

C语言指针进阶(2)

1.2函数指针的定义

(函数返回类型)(*指针名)(函数参数);

1.3函数指针的创建与初始化

void test1()
{
}
int test2(int x)
{
return x+1;
}

如上代码,我们创建了两个函数,现在我们可以用两个函数指针来分别指向这俩个函数

我们分别创建两个指针变量p1,p2,都是指针,所以和*结合,即(*p1),(*p2),

因此,我们可以使用如下代码完成对函数指针的初始化,即

void (*p1)()=&test1;
//p1与*结合,代表p1是指针,去掉(*p1),剩下的void (),表示p1指向的是一个
返回类型为void,函数参数为空的函数
int (*p2)(int)=&test2;
//p2与*结合,代表p2是指针,去掉(*p2),剩下的int (int),表示p2指向的是一个
返回类型为int,函数参数为int的函数

当我们输出两个函数和函数指针的地址时,会发现它们是相同的

C语言指针进阶(2)

1.4函数指针的调用

我们在开头提到,函数名和&函数名是等价的,我们再来看看函数指针的创建与初始化,int (*p2)(int)=&test2;这条语句就等价于int (*p2)(int)=test2;

这里的p2也等价于test2(上图可知),因此我们在调用test2函数时,也可以用函数指针,因为test2(3)就等价p2(3)

我们再定义一个整型来接收函数的返回值,具体如下

int (*p2)(int)=test2;
int ret=p2(3);

1.5初露锋芒

(*(void (*)())0)();//我们来分析一下这行代码代表的含义

1.void (*)():一个函数指针类型

2.(void (*)())0):把0强制转化为函数指针所指向函数的地址,也就是说此处代表一个函数地址

3.(*(void (*)())0)():解引用调用该函数

具体解释

//当你看到void (*)()时有没有很眼熟,

当我们写成void (*p)()时是不是创建了一个函数指针p,p指向的是一个返回类型为空,函数参数为空的函数,那么  void (*)()是不是指针p的类型(p就是个地址),同时也是该函数的地址,而(void (*)())0)就代表把0强制类型转化为该函数的地址,说明白一点(void (*)())0)表示的就是一个函数的地址

再加上*就表示调用该函数

1.6大展身手

void (*signal(int , void(*)(int)))(int)//我们来分析一下这行代码代表的含义

1.signal(int , void(*)(int))

()的优先级高于*,signal先和()结合,代表一个函数,该函数参数一个为int类型,一个为void(*)(int)类型(函数指针类型,该函数指针指向的是一个返回类型为void,函数参数为int的函数

2.void (*)(int):去掉函数名和函数参数后,剩下的是函数的返回类型,显然,

signal函数的返回类型是函数指针类型

二、函数指针数组

存放函数指针的数组

int arr[10]={0};定义了一个数组arr,去掉arr[10]后剩下的int代表数组元素的类型

int (*p[10])();

代码解析:[]的优先级高于*,p先和[]结合,是一个数组,去掉p[10],剩下int (*)(),表示数组p的元素类型为函数指针