LV070-函数指针
为了汇总,这里需要使用函数的概念,函数的详情可以看下一章。
一、函数指针简介
如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码 分配一段存储空间,这段存储空间的首地址称为这个函数的地址。函数名表示的就是这个地址。通过指针的概念,我们知道既然是地址,那么就可以定义一个指针变量来存放,这个 指针变量 就叫作函数指针变量,简称 函数指针。
1. 怎么声明
1.1 基本格式
<数据类型> (*<函数指针名称>) (<参数说明列表>);| 数据类型 | 函数指针所指向的函数的返回值类型 |
| (*<函数指针名称>) | *说明为指针()不可缺省,表明为函数的指针 |
| 参数说明列表 | 应该与函数指针所指向的函数的形参说明保持一致 |
【注意】指向函数的指针变量没有 ++ 和 -- 运算。
1.2 声明示例
例如:
int (*p)(int, int);这个语句定义了一个指向函数的指针变量 p :
(1)它是一个 指针变量,所以要有一个 * ,即( *p );
(2)前面的 int 表示这个指针变量可以 指向返回值类型为 int 型的函数;
(3)括号中的两个 int 表示这个指针变量可以 指向有两个参数且都是 int 型的函数。
所以总体来说,这个语句的意思就是:定义了一个指针变量 p ,该指针变量可以指向返回值类型为 int 型,且有两个整型参数的函数。 p 的类型为 int (*)(int,int) 。
2. 怎么使用
2.1 初始化
前边需要有一个函数的声明:
int sum(int a, int b); /* 函数声明 */| 初始化写法 | 等价写法(赋值) |
| int (*p)(int, int) = sum; | int (*p)(int, int); p = sum; |
2.2 调用
[ <变量名> = ] (*<函数指针名称>)(<实际传入参数说明列表>);例如:
/* 提前定义的函数 */
int sum(int a, int b); /* 函数声明 */
/* -------------------------------------------------- */
/* 主程序中函数指针的操作 */
int (*p)(int, int) = sum; /* 定义一个函数指针 */
printf("a=%d,b=%d,(*p)(a, b)=%d\n", a, b, (*p)(a, b));
/* -------------------------------------------------- */
/* 或者 */
int c = 0;
int (*p)(int, int) = sum; /* 定义一个函数指针 */
c = (*p)(a, b);
printf("a=%d,b=%d,c=%d\n", a, b, c);二、存储空间?
我们写一个实例看看:
#include <stdio.h>
int sum(int a, int b); /* 函数声明 */
int main(int argc, char *argv[])
{
int a = 3;
int b = 2;
int c = 0;
int (*p)(int, int) = sum; /* 定义一个函数指针 */
c = (*p)(a, b);
printf("a=%d,b=%d,c=%d\n", a, b, c);
printf("&a=%p,&b=%p,&c=%p\n", &a, &b,&c);
printf("&sum=%p,p=%p,&p=%p\n", sum, p, &p);
return 0;
}
int sum(int a, int b)
{
return (a + b);
}这个其实也没啥好说的,函数名就是个地址,直接把地址赋给函数指针,和前面普通指针的用法是一样的,可以看到下面的打印信息:
三、函数指针类型
1. 定义格式
上边我们已经知道了可以按照下边的形式定义一个函数指针:
<数据类型> (*<函数指针名称>) (<参数说明列表>);可是当参数列表中参数很多的时候,就显得很麻烦,这个时候我们可以借助 typedef 来定义一个函数指针类型:
typedef <数据类型> (*<函数指针名称>) (<参数说明列表>);2. 使用实例
#include <stdio.h>
typedef int (*MyFunc)(int, char);
int func1(int a, char b);
int func2(int a, char b);
int main(int argc, char *argv[])
{
int (*p)(int, char);/* 定义一个可以指向带有int和char类型参数且返回值为int类型的函数指针变量 */
MyFunc pfunc; /* 与上边的含义相同 */
p = func1;
printf("func1 return:%d\n", (*p)(5, 'a'));
p = func2;
printf("func1 return:%d\n\n", (*p)(6, 'b'));
pfunc = func1;
printf("func1 return:%d\n", (*pfunc)(5, 'a'));
pfunc = func2;
printf("func1 return:%d\n", (*pfunc)(6, 'b'));
return 0;
}
int func1(int a, char b)
{
printf("func1:a = %d, b = %c\n", a, b);
return 1;
}
int func2(int a, char b)
{
printf("func2:a = %d, b = %c\n", a, b);
return 2;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,终端会有以下信息显示:
func1:a = 5, b = a
func1 return:1
func2:a = 6, b = b
func1 return:2
func1:a = 5, b = a
func1 return:1
func2:a = 6, b = b
func1 return:2可见两种定义其实是完全一致的。
四、函数指针数组
6.1 定义
函数指针数组是一个保存若干个函数名的数组,一般形式如下:
<数据类型> (*<函数指针数组名称> [<大小>] )(<参数说明列表> );其中,<大小> 是指函数指针数组元数的个数,其它同普通的函数指针。
例如:
int (*pFunction[3])(int, int);以上语句定义了一个指针数组 pFunction ,该指针数组的元素都是 int 型函数指针,可以指向返回值类型为 int 型,且有两个整型参数的函数。
6.2 使用示例
#include <stdio.h>
typedef int (*MyFunc)(int, char);
int func1(int a, char b);
int func2(int a, char b);
int main(int argc, char *argv[])
{
int (*p[2])(int, char); /* 定义一个可以指向带有int和char类型参数且返回值为int类型的函数指针数组 */
MyFunc pfunc[2]; /* 定义一个可以指向带有int和char类型参数且返回值为int类型的函数指针数组 */
p[0] = func1;
p[1] = func2;
printf("func1 return:%d\n", (*p[0])(5, 'a'));
printf("func2 return:%d\n\n", (*p[1])(6, 'b'));
pfunc[0] = func1;
pfunc[1] = func2;
printf("func1 return:%d\n", (*pfunc[0])(7, 'c'));
printf("func2 return:%d\n", (*pfunc[1])(8, 'd'));
return 0;
}
int func1(int a, char b)
{
printf("func1:a = %d, b = %c\n", a, b);
return 1;
}
int func2(int a, char b)
{
printf("func2:a = %d, b = %c\n", a, b);
return 2;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,终端会有以下信息显示:
func1:a = 5, b = a
func1 return:1
func2:a = 6, b = b
func2 return:2
func1:a = 7, b = c
func1 return:1
func2:a = 8, b = d
func2 return:2