当前位置: 首页 > news >正文

C语言 指针(7)

目录

1.函数指针变量

2.函数指针数组

3.转移表


1.函数指针变量

1.1函数指针变量的创建

什么是函数指针变量呢?
 
根据前面学习整型指针,数组指针的时候,我们的类比关系,我们不难得出结论:

函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数的。
 
那么函数是否有地址呢?

我们做个测试:

#include <stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test:  %p\n", test);printf("&test: %p\n", &test);return 0;
}

输出结果如下:

1. test:  005913CA
2. &test: 005913CA

确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名

的方式获得函数的地址。
 
如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指

针非常类似。如下:

void test()
{printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)() = test;int Add(int x, int y)
{return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add; //x和y写上或者省略都是可以的

函数指针类型解析:

int     (*pf3)   (int x, int y)
|       |        |
|       |        |-- pf3指向函数的参数类型和个数的交代
|       |
|       |-- 函数指针变量名
|
|-- pf3指向函数的返回类型
int (*) (int x, int y) //pf3函数指针变量的类型

1.2函数指针变量的使用

通过函数指针调用指针指向的函数

#include <stdio.h>
int Add(int x, int y) {return x + y;
}
int main() {int(*pf3)(int, int) = Add;printf("%d\n", (*pf3)(2, 3));printf("%d\n", pf3(3, 5));return 0;
}

输出结果:

1. 5
2. 8

1.3 typedef关键字

typedef 是用来给类型重命名的,可以把复杂的类型变得简单。
 
比如,觉得  unsigned int  写起来麻烦,要是能写成  uint  就方便多了,那就可以这样用:

typedef unsigned int uint; 
//把unsigned int 重命名成uint

指针类型也能重命名,比如把 int*  重命名成 ptr_t  ,像这样:

typedef int* ptr_t;

不过对于数组指针和函数指针,重命名有点不一样。
 
比如有个数组指针类型  int(*)[5]  ,要把它重命名成  parr_t  ,就得这么写:

typedef int(*parr_t)[5]; 
//新的类型名必须在*的右边

函数指针类型的重命名也是一样的,比如,将 void(*)(int)  类型重命名为 pf_t ,就可以这样写:

typedef void(*pfun_t)(int); //新的类型名必须在*的右边

2.函数指针数组

数组是一个存放相同类型数据的存储空间,我们已经学习了指针数组,比如:

int * arr[10]; 
//数组的每个元素是int*

那要把函数的地址存到一个数组中,那个数组就叫函数指针数组,那函数指针的数组如何定义呢?

int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3];

答案是: parr1 

parr1  先和  []  结合,说明  parr1  是数组,数组的内容是什么呢?

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

3.转移表

函数指针数组的用途: 转移表

举例:计算器的一般实现

#include <stdio.h>
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;do{printf("********************\n");printf("  1:add        2:sub \n");printf("  3:mul        4:div \n");printf("  0:exit              \n");printf("********************\n");printf("请选择: ");scanf("%d", &input);switch (input){case 1:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}

代码解释 :

(1)头文件的引入:

#include <stdio.h>

 #include <stdio.h>  指令用于引入标准输入输出头文件,该文件包含了  printf 、 scanf  等输入输

出函数的声明,使得程序能够进行输入输出操作。

(2)函数定义:

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;
}

这里定义了四个函数,分别是 add(加法)、sub (减法)、mul (乘法)、div (除法)。每

个函数都接收两个 int  类型的参数,并根据相应的运算规则返回计算结果。

(3)main函数:

int main()
{int x, y;int input = 1;int ret = 0;

-  int x, y;  声明了两个整型变量  x  和  y ,用于存储用户输入的操作数。

-  int input = 1;  声明并初始化了变量  input ,用于存储用户选择的操作选项,初始值设为  1  是为

了确保  do - while  循环至少执行一次。

-  int ret = 0;  声明并初始化了变量  ret ,用于存储运算结果,初始值为  0  。

(4)do-while循环

    do{printf("********************\n");printf("  1:add        2:sub \n");printf("  3:mul        4:div \n");printf("  0:exit              \n");printf("********************\n");printf("请选择: ");scanf("%d", &input);

-  do - while  循环保证了循环体至少执行一次。

- 循环体中,首先通过  printf  函数打印出操作选项菜单,提示用户进行选择。然后使用  scanf  函

数读取用户输入的整数,并存储到  input  变量中。

(5)switch语句:

        switch (input){case 1:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入操作数: ");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);

-  switch  语句根据  input  的值来执行不同的分支:

-  case 1 :当用户选择  1  时,提示用户输入两个操作数,然后使用  scanf  读取,再调用  add  函

数进行加法运算,将结果存储在  ret  中,并打印出结果。

-  case 2 :与  case 1  类似,调用  sub  函数进行减法运算。

-  case 3 :调用  mul  函数进行乘法运算。

-  case 4 :调用  div  函数进行除法运算。不过这里没有对除数为  0  的情况进行处理,如果用户

输入  0  作为除数,程序会产生未定义行为。

-  case 0 :当用户选择  0  时,打印“退出程序”,此时  input  的值为  0 , do - while  循环条件不

满足,程序结束。

-  default :当用户输入的不是  0  -  4  之间的数字时,打印“选择错误”。

-  do - while  循环的条件是  input ,只要  input  不为  0 ,循环就会继续执行,用户可以不断进行操作选择。

(6)函数返回:

    return 0;
}

 main  函数返回  0  ,表示程序正常结束。在C语言中, main  函数返回  0  通常用于向操作系统表

明程序执行成功。

希望大家能够好好理解转移表这块的代码,感谢大家的观看!

相关文章:

  • 【工具变量】数字人民币试点城市DID(2007-2024年)
  • 【心海资源】0U攻击工具|一键模仿地址生成+余额归集+靓号生成系统
  • 神经网络:节点、隐藏层与非线性学习
  • Ubuntu 系统详解
  • Unable to determine the device handle for GPU0000:82:00.0: Unknown Error
  • 知乎前端面试题及参考答案
  • 用于备份的git版本管理指令
  • DC-DC降压型开关电源(Buck Converter)设计中,开关频率(f sw​ )、滤波电感(L)和滤波电容(C out​ )的关系和取舍
  • JDBC实现--保姆级教程~
  • 【东枫科技】代理英伟达产品:智能网卡
  • 【东枫科技】代理英伟达产品:交换机系统
  • Mysql group by 用法
  • 安装篇--CentOS 7 虚拟机安装
  • C++学习之路,从0到精通的征途:stack_queue的模拟实现及deque原理介绍
  • 安卓基础(拖拽)
  • 信奥赛CSP-J复赛集训(DP专题)(37):P4170 [CQOI2007] 涂色
  • RabbitMQ ①-MQ | Linux安装RabbitMQ | 快速上手
  • 解锁健康生活:全新养身指南
  • HPE推出零信任网络与私有云运维解决方案
  • 盘古信息领德创|半导体存储与云计算存储小巨人企业IMS数字化升级项目正式启动!
  • 央行:今日起下调再贷款利率0.25个百分点
  • 巴菲特掌舵伯克希尔60年后将卸任CEO,库克:认识他是人生中最珍贵的经历之一
  • 五问舆论漩涡中的“协和‘4+4’模式”:是否公平,如何合格?
  • 对谈|“对工作说不”是不接地气吗?
  • AI世界的年轻人|他用影像大模型解决看病难题,“要做的研究还有很多”
  • 特朗普宣布提名迈克·沃尔兹为下一任美国驻联合国大使