函数指针数组
要了解函数指针数组,先来看数组的定义
int a[10] = {0};
再看函数指针的定义
void p(){
printf(“hellow world\n”);
}
void (*p)();//这就是一个函数指针,顾名思义,首先它是一个指针,里面存的是函数p 的入口地址
接下来就是函数指针数组的定义
int (*p[10])(int x,int y);
对于此类复杂式子,可以根据优先级判断:
先看()里,首先 [] 的优先级高于 * ,所以p先和 [] 结合,所以首先是一个数组
再看第二个(),说明是一个函数
一次该表达式定义了一个函数指针数组
对于分辨这种复杂的表达式,完全可以根据操作符的优先级来判断。
转移表:
转移表就是函数指针数组的用途,通过函数指针可以得出,函数的入口地址可以被保存起来,这就意味着完全可以通过入口地址来调用函数,而函数指针又可以存入到一个指针数组(函数指针数组)中,即可以通过数组下标来调用函数。
下面来看转移表的简单示例:简单计算器
先来用常规方法实现:
#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( "*************************\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");
breark;
default:
printf( "选择错误\n" );
break;
}
} while (input);
return 0;
}
#include <stdio.h>
int add(int a, int b)
{
return a + b;
在这个代码中,加 减 乘 除返回值都是int类型,而且都要进行输入x,y,所以 printf( “输入操作数:” );
scanf( “%d %d”, &x, &y); 这部分代码一直都在重复,增加了程序开销
再来看使用转移表的代码,这里采用多文件形式
头文件:
#pragma once
#include<stdio.h>
#include<windows.h>
#pragma warning(disable:4996)
int add(int, int);//运算声明
int sub(int, int);//声明时可以不写参数名
int mul(int, int);
int dive(int, int);
void Mene();//目录
实现文件:
#include"hanshu.h"//首先包含之前定义的头文件
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 dive(int x, int y){
if (y == 0){
printf("输入有误\n");
return -1;
}
else{
return x / y;
}
}
void Mene(){
printf("###################################\n");
printf("###1:add 2:sub###\n");
printf("###3:mul 4:dive###\n");
printf("###0:quit ####\n");
printf("###################################\n");
printf("Enter your number ->");
}
主函数(测试函数):
#include"hanshu.h"
int main(){
int quit = 1;
int select = 1;
int(*p[4])(int x, int y) = { add, sub, mul, dive };//定义一个函数指针数组(转移表)并初始化,将个函数的入口地址写入该数组
while (quit){
Mene();
scanf("%d", &select);
if (select == 0){
quit = 0;
continue;
}
else{
int x = 0;
int y = 0;
printf("输入你的操作数:\n");
scanf("%d %d", &x, &y);
int result = p[select - 1](x, y);//直接通过下标来调用函数
printf(" 结果是 :%d\n", result);
}
}
printf("Bye Bye!");
system("pause");
return 0;
}
可以明显看出,使用转移表节省去很多的不必要的代码,减小了代码量;
对于函数指针的理解,可以类似的用数组来理解,数组的地址就是首元素的地址,函数的地址就是入口地址(仅限理解,因为只是本人的理解,,,手动狗头)
有不足或不对的地方欢迎大佬更正嘻嘻嘻