C语言-指针进阶-函数指针数组应用-计算器(9.2)

简介: C语言-指针进阶-函数指针数组应用-计算器(9.2)

思维导图:




1. 函数指针

直接上代码:


#include 
void test()
{
  printf("hehe\n");
}
int main()
{
  printf("%p\n", test);
  printf("%p\n", &test);//取函数地址
  return 0;
}


输出:


输出:

00F013CF

00F013CF

打印出来的其实就是函数的地址,


通过观察我们发现函数名的地址与&函数名其实是一样的。


那我们该如何存储函数的地址呢?


例:


#include 
void test()
{
  printf("hehe\n");
}
int main()
{
  //*与指针名先结合,左边是函数返回类型,右边是函数传的参数
  void (*pfun1)() = &test;//因为test与&test其实是一样的
                         //所以&是可以省略的
  return 0;
}

学到这里,我们读两段有趣的代码:


int main()
{
  (*(void (*)())0)();
  void (*signal(int, void(*)(int)))(int);
  return 0;
}
他们分别代表着什么呢?
int main()
{
  (*(void (*)())0)();
  //这是一段函数调用,
  //将0强制类型转换成一个类型是void (*)()的函数指针
  //然后调用0地址处的函数
  void (*signal(int, void(*)(int)))(int);
  //这是一段函数声明,
  //声明的是一个函数名是signal
  //返回类型是void(*)(int)类型的函数指针
  //参数类型是int和void(*)(int)的一个函数
  return 0;
}


2. 函数指针数组

2.1函数指针数组的定义

函数指针数组是什么?


其实就是一个数组的每个元素都是函数指针。


例:


int main()
{
  int (*parr1[10])();
  //这就是一个函数指针数组,parr1与[10]先结合表面他是一个数组
  //而他这个数组每个元素的类型是int(*)()的函数指针
  return 0;
}

2.2函数指针数组应用

函数指针究竟有什么用呢?


我们实现一个计算器试试:


一般的思路:


#include 
//函数实现
int Add(int x, int y)
{
  return x + y;
}
int Sub(int x, int y)
{
  return x - y;
}
int Mul(int x, int y)
{
  return x * y;
}
int Div(int x, int y)
{
  return x / y;
}
//菜单打印
void menu()
{
  printf("1.加法\n2.减法\n3.乘法\n4.除法\n0.退出\n");
}
void test()
{
  int input = 0;
  int x = 0, y = 0;
  int ret = 0;
  do
  {
  menu();
  printf("请选择:>");
  scanf("%d", &input);
  switch(input)
  {
  case 1:
    printf("请输出:>");
    scanf("%d %d", &x, &y);
    ret = Add(x, y);
    printf("%d\n", ret);
    break;
  case 2:
    printf("请输出:>");
    scanf("%d %d", &x, &y);
    ret = Sub(x, y);
    printf("%d\n", ret);
    break;
  case 3:
    printf("请输出:>");
    scanf("%d %d", &x, &y);
    ret = Mul(x, y);
    printf("%d\n", ret);
    break;
  case 4:
    printf("请输出:>");
    scanf("%d %d", &x, &y);
    ret = Div(x, y);
    printf("%d\n", ret);
    break;
  case 0:
    printf("计算器已退出\n");
    break;
  default:
    printf("输入错误,请重新输入\n");
    break;
  }
  } while (input);
}
int main()
{
  test();//分装函数实现
  return 0;
}


但是我们发现这样实现代码量太多,


或者说代码重复的部分太多,代码冗余,那我们该如何改进呢?


利用函数指针数组的思路:

#include 
//菜单打印
void menu()
{
  printf("1.加法\n2.减法\n3.乘法\n4.除法\n0.退出\n");
}
//函数实现
int Add(int x, int y)
{
  return x + y;
}
int Sub(int x, int y)
{
  return x - y;
}
int Mul(int x, int y)
{
  return x * y;
}
int Div(int x, int y)
{
  return x / y;
}
//函数指针数组存放上述函数的地址
int (*pf[5])(int, int) = { NULL, Add, Sub, Mul, Div };
void test()
{
  int input = 0;
  int x = 0;
  int y = 0;
  int ret = 0;
  do
  {
  menu();
  printf("请选择:>");
  scanf("%d", &input);//这里输入函数指针数组的下标
  if (input == 0)//用if else语句判断退出和选择错误的特殊情况
  {
    printf("退出计算器\n");
    break;
  }
  else if (input >= 1 && input <= 4)//使用计算器的情况
  {
    printf("请输入两个操作数:>");
    scanf("%d %d", &x, &y);
    ret = pf[input](x, y);//通过函数指针数组调用函数
    printf("%d\n", ret);
  }
  else
  {
    printf("选择错误\n");
  }
  } while (input);
}
int main()
{
  test();//分装函数实现
  return 0;
}

这样写,代码冗余的问题也解决了,


这就是函数指针数组的一个应用场景,


当然,函数指针数组也有一定的缺陷,比如实现这个计算器时:


想要通过数组访问,每个函数指针的参数必须要相同。


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

我们学了函数指针,


又学了函数指针数组,


当然也有指向函数指针数组的指针啦!


例:

int Add(int x, int y)
{
  return x + y;
}
int main()
{
  int(*padd)(int, int) = Add; //这是一个函数指针
  int(*parr[5])(int, int);//这是一个函数指针数组
  int(*(*pparr)[5])(int, int) = &parr;
  //*与指针名先结合,证明这是一个指针,与[]相连证明这是一个数组指针,
  //而这个数组指针每个元素的类型是int(*)(int,int)的函数指针,
  //这就是一个指向函数指针数组的指针。
  return 0;
}



写在最后:

以上就是本篇文章的内容了,感谢你的阅读。


如果喜欢本文的话,欢迎点赞和评论,写下你的见解。


如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。


相关文章
|
1月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
64 4
|
29天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
48 0
|
28天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
17 2
|
28天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
28天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
28天前
|
编译器 C语言
【c语言】指针就该这么学(2)
本文详细介绍了指针与数组的关系,包括指针访问数组、一维数组传参、二级指针、指针数组和数组指针等内容。通过具体代码示例,解释了数组名作为首元素地址的用法,以及如何使用指针数组模拟二维数组和传递二维数组。文章还强调了数组指针与指针数组的区别,并通过调试窗口展示了不同类型指针的差异。最后,总结了指针在数组操作中的重要性和应用场景。
19 0
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
25 0
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
3月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)