【C生万物】 指针篇 (进级) 下(二)

简介: 【C生万物】 指针篇 (进级) 下

正文


Part5:函数指针


1.引入


既然指向单个变量的指针,有指向数组的指针,那么有没有指向函数的指针?


欸,还真有:


下面一段代码可以证明:


void test()
{
  printf("Hello\n");
}
int main()
{
  printf("%p\n", test);
  printf("%p\n", &test);
  return 0;
}


👁️‍🗨️输出结果:


786e55351e83297e2070c43e6c976926_09ea256bd3b6499bae76cbd7b202ffda.png


可见函数是有地址的,既然有地址,就可以存放起来作为指针;


并且:&函数名 与 函数名 都表示函数的地址。


2.表示



我先放出两种,你看看那种行得通:


// fun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();


答:pfun1可以,( )内优先,* 与pfun1 先结合,说明 pfun1 是个指针,指向的是一个函数,指向的函数无参数,也无返回类型。


来个复杂的:


// 写出下列函数的函数指针
int Add(int x, int y)
{
  return x + y;
}


答:


int (*pf)(int, int) = &Add;
// 开头是返回类型,最后的括号里是参数类型


函数指针的写法与数组指针的写法非常类似,可以类比着来。


使用:


int (*pf)(int, int) = &Add;
int ret = pf(2, 3);
int ret = (*pf)(2, 3);


两种使用方法均可。


Part6:函数指针数组


1.引入


我们已经学过了常量数组,指针数组,那么函数指针数组呢?


函数指针数组的解读就是:


一个数组,里面的元素类型为函数指针。


2.表示


知道了函数指针数组的含义,怎么表示呢?


// 哪个是函数指针数组?
int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];


答:parr1 是函数指针数组


解释:parr1 先与[ ]结合,说明 parr1 是数组,那数组的内容呢?


int (*)() 类型的函数指针。


3.应用


函数指针数组是有实际应用的,就是 转移表


说名字挺难理解的,这里举一个例子:


现在要你用C语言写一个计算器,菜单如下:


dbfe2c11622180bb93fe99b0b3060bf4_d33b63b3e0934975ade58e3e4aca23fe.png


输入1是加法,输入2是减法,输入3是乘法,输入4是除法。


我们发现这种应用有一个特点:就是要调用多个不同的函数,


如果我们用 switch - case 语句,每个判断语句下调用相应的函数,那岂不是太挫了?


所以就要用到 转移表 ,即把 多个函数的指针存放到一个数组当中,需要就按下标访问调用即可。


代码实现


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 main()
{
  int x, y;
  int input = 1;
  int ret = 0;
  int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //定义函数指针数组,作转移表
  while (input)
  {
    printf("*************************\n");
    printf("*  1:add         2:sub  *\n");
    printf("*  3:mul         4:div  *\n");
    printf("*************************\n");
    printf("请选择:");
    scanf("%d", &input);
    if ((input <= 4 && input >= 1))
    {
      printf("输入操作数:");
      scanf("%d %d", &x, &y);
      ret = (*p[input])(x, y);
    }
    else
      printf("输入有误\n");
    printf("ret = %d\n", ret);
  }
  return 0;
}

是不是很方便呢?


Part7:回调函数


1.定义


回调函数就是一个通过函数指针调用的函数 。

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。


简单来说,回调函数就是利用函数指针,实现函数调用函数的操作。


2.应用


那么回调函数是怎么应用的呢?


这里有个实例,就是冒泡排序模拟 qsort 函数,正好往期介绍过了,可以直接跳转:


冒泡排序模拟qsort函数


总结:


本篇是指针进级的最后一篇,到这里我相信你已经对指针有着很深刻的理解了,这么来看,指针还不是最困难的,对吧?


码文不易


如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦  💗💗💗


目录
相关文章
C生万物 | 从浅入深理解指针【最后部分】(二)
C生万物 | 从浅入深理解指针【最后部分】(二)
|
5月前
|
存储 C++
C生万物 | 从浅入深理解指针【第三部分】(转移表的实现)
C生万物 | 从浅入深理解指针【第三部分】(转移表的实现)
C生万物 | 从浅入深理解指针【第二部分】(二)
C生万物 | 从浅入深理解指针【第二部分】(二)
|
5月前
|
编译器
C生万物 | 从浅入深理解指针【第二部分】(一)
C生万物 | 从浅入深理解指针【第二部分】 前言: 如果没有看过第一部分的话,推荐先看第一部分,然后再来看第二部分~~
|
5月前
|
存储 C语言 C++
C生万物 | 从浅入深理解指针【第一部分】(一)
C生万物 | 从浅入深理解指针【第一部分】
|
5月前
|
机器学习/深度学习 安全 程序员
C生万物 | 从浅入深理解指针【第一部分】(二)
C生万物 | 从浅入深理解指针【第一部分】(二)
|
5月前
|
C语言 C++
C生万物 | 从浅入深理解指针【最后部分】(一)
C生万物 | 从浅入深理解指针【最后部分】(一)
C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)
C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)
|
10月前
|
存储 编译器 C语言
C生万物 | 指针进阶 · 炼狱篇-3
C生万物 | 指针进阶 · 炼狱篇
60 0
|
10月前
C生万物 | 指针进阶 · 炼狱篇-2
C生万物 | 指针进阶 · 炼狱篇
45 0