【C语言进阶】函数指针、函数指针数组、指向函数指针数组的指针
文章目录
- 【C语言进阶】函数指针、函数指针数组、指向函数指针数组的指针
- 五、函数指针
- 1 示例1
- 2 示例2
- 3 示例3
- 4 练习实例
- 4.1 示例1
- 4.2 示例2
- 六、函数指针数组
- 1 函数指针数组的定义
- 2 示例1
- 2.1 计算器(普通实现)
- 2.2 计算器(函数指针数组实现)
- 七、指向函数指针数组的指针
- 总结:
五、函数指针
函数指针就是指向函数的指针,函数指针变量存放函数的地址。
1 示例1
代码示例:
#include<stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
//函数指针
printf("%p\n", test);//函数名会被隐式转换为函数的地址
printf("%p\n", &test);//&函数名表示函数的地址
return 0;
}
解释说明:
1 输出的结果都是 test
函数的地址。
2 示例2
代码示例:
#include<stdio.h>
void test(char* pc, int arr[10])
{
printf("haha\n");
}
int main()
{
//函数指针
int arr[10] = { 0 };
char ch = 0;
test(ch, arr);
void (*pf)(char*, int[]) = &test;//指向函数的指针变量
//void (*pf)(char*, int[10]) = &test;
//void (*pf)(char*, int*) = &test;
//&test可以写成test,但是加上&会更直观地显示这是函数的地址
return 0;
}
解释说明:
1 void (*pf)(char*, int[]) = &test;
:pf
先与*结合,说明 pf
是一个指针;
指针指向的是一个函数,指向的函数参数为 char*, int[]
,返回值类型为 void
。
2 在声明函数指针的时候,函数形参的名字可以省略,但是必须明确形参个数与形参类型,和函数的声明一样。
3 示例3
代码示例:
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
//函数指针
int (*pf)(int, int) = &Add;
int l = Add(3, 5); //函数调用
int m = (*pf)(3, 5);//通过指针间接调用函数
int n = pf(3, 5); //通过指针间接调用函数
printf("l = %d\n", l);//8
printf("m = %d\n", m);//8
printf("n = %d\n", n);//8
return 0;
}
解释说明:
1 可以通过函数指针间接调用函数。
2 调用方式可以写成:(*pf)()
或 pf()
,两者表达的意思一致。
4 练习实例
4.1 示例1
示例:
(*(void(*)())0)();
解释说明:
1.将0地址强制类型转换为
void(*)()
类型的函数指针2.调用0地址处的函数
//先定位到0,0可以表示:
0 -- int -- 整型值
0 -- int* -- 地址
//0前的括号表示:
()0 -- 强制类型转换
//0前的括号内,类型为:
void(*)() -- 函数指针类型:指向的函数无参数,且函数的返回值为void
//0被强制类型转换为:
(void(*)())0 --> 将 0地址 强制类型转换为 void(*)() 类型的函数指针
//剩下的内容
(*)() --> 使用函数指针间接调用函数
//代码解释:
(*(void(*)())0)(); --> 调用0位置处的这个函数
类比说明:
//0 可以是一个整型int的值,也可以是一个整型地址:int*。
//0X0012FF40 可以是一个十六进制的整数,也可以是一个地址。
4.2 示例2
说明:
void (*signal(int, void(*)(int)))(int);
解释说明:
//先定位到signal:
signal(int, void(*)(int)) --> 函数声明
函数参数为:int -- 整型、void(*)(int) -- 函数指针(指针指向的函数参数为int,返回值为void)
//剩余部分
void(*)(int) --> 充当返回值类型
//这是一个函数声明,正常的阅读顺序为:
返回值类型 函数名 函数参数
void(*)(int) signal(int, void(*)());//signal函数声明,意思正确,写法错误
//此句代码表示的是:signal函数的声明;
//signal函数有两个参数:一个是整型,一个是函数指针,该函数指针指向的函数没有参数,函数的返回值是void;
//最后signal函数返回的也是该类型的函数指针。
简化函数声明:
typedef void(*pfunc)(int); --> 阅读顺序:typedef void(*)() pfunc;//意思正确,写法错误
pfunc signal(int,pfunc);
六、函数指针数组
函数指针数组是一个存放**函数指针变量(或者说是函数地址)**的数组。
函数指针数组的用途:转移表
1 函数指针数组的定义
示例:
int (*parr1[10])(); --> 数组元素类型:int(*)()(函数指针)
int *parr2[10]();//error
int(*)() parr3[10];//error
2 示例1
2.1 计算器(普通实现)
代码示例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.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 div(int x, int y)
{
return x / y;
}
void menu()
{
printf("<**************************>\n");
printf("<****> 1.add 2.sub <****>\n");
printf("<****> 3.mul 4.div <****>\n");
printf("<****> 0.exit <****>\n");
printf("<**************************>\n");
}
int main()
{
//计算器(普通实现)
int x, y;
int input = 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("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;
}
2.2 计算器(函数指针数组实现)
代码示例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.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 div(int x, int y)
{
return x / y;
}
void menu()
{
printf("<**************************>\n");
printf("<****> 1.add 2.sub <****>\n");
printf("<****> 3.mul 4.div <****>\n");
printf("<****> 0.exit <****>\n");
printf("<**************************>\n");
}
int main()
{
//计算器(函数指针数组实现)
int x, y;
int input = 1;
int ret = 0;
//函数指针数组
int(*p[5])(int, int) = { 0,add,sub,mul,div };//转移表
while (input)
{
menu();
printf("请选择项目:>");
scanf("%d", &input);
if ((input <= 4) && (input >= 1))
{
printf("请输入操作数:>");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
//ret = p[input](x, y);//同上
printf("ret = %d\n", ret);
}
else if (0 == input)
{
printf("退出程序!\n");
break;
}
else
{
printf("选择错误,请重新输入!\n");
}
}
return 0;
}
七、指向函数指针数组的指针
指向函数指针数组的指针是一个指针变量,该指针指向一个数组,数组元素为函数指针。
代码示例:
#include<stdio.h>
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = &test;
//函数指针数组pfunArr
void (*pfunArr[5])(const char*);
pfunArr[0] = &test;//pfunArr[0] = pfun;
//指向函数指针数组pfunArr的指针PpfunArr
void (*(*PpfunArr)[5])(const char*) = &pfunArr;
return 0;
}
解释说明:
1 函数指针类型(函数指针数组元素类型):void (*)(const char*)
2 指向函数指针数组的指针类型(函数指针数组的类型):void (*(*)[5])(const char*)
总结:
本节介绍了函数指针、函数指针数组、指向函数指针数组的指针,用示例代码以及注释详细介绍了三者的使用方法与场景。
感谢您的阅读!如有任何错误,欢迎您的批评指正!