C语言进阶——指针(二)

一.   函数指针

说到指针,我们可以想到的是取地址操作符

int ADD(int a,int b)
{
    return a+b;
}
int main()
{
    printf("%p\n", &ADD);
    return 0;
}

  

如此,我们便可以得到一个地址

而我们便可以将这个地址存入到一个函数指针中

int(*p)(int,int)=&ADD

类似于数组指针,我们可以采用类似的方法来思考,其中*表示p为指针变量,int表示函数的返回值的类型,而(int ,int)表示的是函数参数的类型

然而事实上,函数名本身所代表的就是函数的地址,与&函数名一致

int ADD(int a,int b)
{
    return a+b;
}
int main()
{
    printf("%p\n", &ADD);
    printf("%p\n", ADD);
    return 0;
}

 

 我们可以看到,test与&test所代表的地址都是相同的

因此,我们也可以将函数指针写作这样

int(*p)(int,int)=print

而在使用时,与指针类似,我们可以解引用后使用

printf("%d",(*p)(2,3));

而事实上,不进行解引用操作直接使用也是可以的

printf("%d",p(2,3));

我们来看两端有趣的代码

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);

 首先代码1,我们可以由内到外来分析,首先,void(*)()是一个函数指针类型,无返回值,无参数。而(void(*)())0也就表示将地址为0的函数指针进行强制类型转换。而转换后外层的(*   )()表示该函数指针解引用后进行使用。

而代码2,首先我们可以确定signal为一个函数名,它有两个参数int 和void(*)(int),在分离  signal(int , void(*)(int))后,剩下void(*   )(int),可以得知是一个函数指针的类型,因此signal的返回类型也应该是一个函数指针

而将代码2简化后,也会更容易理解

typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);


二.   函数指针数组

在上面,我们学习了函数指针,而函数指针数组也就很好理解了,就是一个存放函数指针的数组

例如若是想要实现一个简易的计算器(加减乘除)

需要分别自定义四个函数来实现这些功能

int add(int a, int b)
{
	return a + b;
}

int sub(int a, int b)
{
	return a - b;
}

int mul(int a, int b)
{
	return a * b;
}

int div(int a, int b)
{
	return a / b;
}

由于参数类型、参数个数、返回类型都相同,我们可以将这四个函数放在一个函数指针数组中,以便于调用

int(*p[4])(int a, int b) = { add, sub, mul, div };

同样,int 表示函数返回值类型,*表示指针,[4]表示这是一个数组,(int a, int b)表示函数参数

这样也就方便函数的调用



三.   指向函数指针数组的指针

没啥好解释的,就想名字一样

int(*p[4])(int a, int b) = { add, sub, mul, div };
int(*(*pp[4]))(int a, int b)=&p;


四.   回调函数

概念

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
行响应。
紧承上面所讲的计算器,但我们不再使用函数指针数组

int add(int a, int b)
{
	return a + b;
}

int sub(int a, int b)
{
	return a - b;
}

int mul(int a, int b)
{
	return a * b;
}

int div(int a, int b)
{
	return a / b;
}

首先,回调函数的参数应该是函数指针

int calc(int (*pf)(int int))
{

}

而当我们想要实现计算器,只需要将对应函数的地址(函数名)传给回调函数即可

calc(add);

而calc内部,也是比较容易实现的

int calc(int (*pf)(int int))
{
    int a=0;
    int b=0;
    int ret=0;
    scanf("%d,%d",&a,&b);
    ret=pf(a,b);
    return ret;    
}

qsort函数

同样,qsort函数中也是一个典型的回调函数

在分析回调函数之前,我们先来了解一下qsort函数

 

 我们可以看到,这个函数有四个参数,分别是base:数组首元素地址、num:数组大小、size数组类型大小以及compar这个用作比较两个元素的函数

而我们主要是来考虑这个compar函数

 

大致分析一下,就是比较两个元素,并分情况-1,0,1

而参数的类型为const void*,无法直接使用,需要进行强制类型转换才可以。

而既然小于返回负数,等于返回0,大于返回正数,我们就可以直接返回两数相减的值即可

int compar(const void * p1, const void * p2)
{
    return (*( int *)p1 - *(int *) p2);
}

 

评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

finish_speech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值