目录
1.函数指针变量
1.1函数指针变量的创建
什么是函数指针变量呢?
根据前面学习整型指针,数组指针的时候,我们的类比关系,我们不难得出结论:
函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数的。
那么函数是否有地址呢?
我们做个测试:
cs
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("test: %p\n", test);
printf("&test: %p\n", &test);
return 0;
}
输出结果如下:
cs
1. test: 005913CA
2. &test: 005913CA
确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 &函数名
的方式获得函数的地址。
如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指
针非常类似。如下:
cs
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写上或者省略都是可以的
函数指针类型解析:
cs
int (*pf3) (int x, int y)
| | |
| | |-- pf3指向函数的参数类型和个数的交代
| |
| |-- 函数指针变量名
|
|-- pf3指向函数的返回类型
int (*) (int x, int y) //pf3函数指针变量的类型
1.2函数指针变量的使用
通过函数指针调用指针指向的函数
cs
#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;
}
输出结果:
cs
1. 5
2. 8
1.3 typedef关键字
typedef 是用来给类型重命名的,可以把复杂的类型变得简单。
比如,觉得 unsigned int 写起来麻烦,要是能写成uint 就方便多了,那就可以这样用:
cs
typedef unsigned int uint;
//把unsigned int 重命名成uint
指针类型也能重命名,比如把int* 重命名成ptr_t,像这样:
cs
typedef int* ptr_t;
不过对于数组指针和函数指针,重命名有点不一样。
比如有个数组指针类型 int(*)[5] ,要把它重命名成parr_t,就得这么写:
cs
typedef int(*parr_t)[5];
//新的类型名必须在*的右边
函数指针类型的重命名也是一样的,比如,将void(*)(int) 类型重命名为pf_t,就可以这样写:
cs
typedef void(*pfun_t)(int); //新的类型名必须在*的右边
2.函数指针数组
数组是一个存放相同类型数据的存储空间,我们已经学习了指针数组,比如:
cs
int * arr[10];
//数组的每个元素是int*
那要把函数的地址存到一个数组中,那个数组就叫函数指针数组,那函数指针的数组如何定义呢?
cs
int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3];
答案是: parr1
parr1 先和 [] 结合,说明 parr1 是数组,数组的内容是什么呢?
是 int (*)() 类型的函数指针。
3.转移表
函数指针数组的用途: 转移表
举例:计算器的一般实现
cs
#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)头文件的引入:
cs
#include <stdio.h>
#include <stdio.h> 指令用于引入标准输入输出头文件,该文件包含了 printf 、 scanf 等输入输
出函数的声明,使得程序能够进行输入输出操作。
(2)函数定义:
cs
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函数:
cs
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循环
cs
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语句:
cs
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)函数返回:
cs
return 0;
}
main 函数返回 0 ,表示程序正常结束。在C语言中, main 函数返回 0 通常用于向操作系统表
明程序执行成功。
希望大家能够好好理解转移表这块的代码,感谢大家的观看!