1.函数指针
上代码:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
输出的是两个地址,这两个地址是 test 函数的地址。
那我们的函数的地址要想保存起来,怎么保存?
void test()
{
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();
答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参
数,返回值类型为void。
再看两段代码:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
代码1是一个‘0’被强制类型转换为void(*)()的函数,在void(*)()左边的‘*’没有实质作用。
代码2是一个复杂的函数声明,是一个类型为void()(int),函数名为signal的函数,其函数的参数类型是int和void(*)(int)。
2.函数指针数组
函数指针数组的写法:
int (*parr[3])(int,char *);
一个数组名为parr的数组,长度为3,其数组每个元素的类型是int (*) (int,char *)。
利用函数指针数组可以实现一个简易的计算器:
#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;
int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
while (input)
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf("****** 0. exit *******\n");
printf("*************************\n");
printf("请选择:");
scanf("%d", &input);
if ((input <= 4 && input >= 1))
{
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
printf("ret = %d\n", ret);
}
else if (input == 0)
printf("退出计算器\n");
else
printf("输入有误\n");
}
return 0;
}
不同于以往的计算器的是,过去写过的计算器都采用的if else或者更多是switch语句的叠用,在这里我们用到一行代码就可以将各个函数功能联系在一个数组上,而用一个数组将几个函数指针串用起来的叫做转移表。
3.指向函数指针数组的指针
指向函数指针数组的指针是一个 指针
指针指向一个 数组 ,数组的元素都是 函数指针;
定于:
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[5])(const char*) = &pfunArr;
return 0;
}