首页 > 代码库 > 指针知识梳理7- 函数指针

指针知识梳理7- 函数指针

一、函数的地址

前面讲 程序运行起来以后,在内存中有代码区,程序执行每一条指令,是从内存中读出来这条指令,然后再执行。
所谓函数的地址是指函数的入口地址,这个函数的从这个地址开始进入执行,也就是从这个地址处取指令执行。
那么在代码层面,函数的地址用 函数指针变量 来存储。

二、基本使用

1、函数指针定义

函数指针的定义,在语法看起来稍微有点怪,只需要记住形式
返回值 (*指针变量名)(形参类型);
比如,以下4个函数
void func1(void)
{
}
int func2(void)
{
}
int func3(int a)
{
}
int func4(int a,int b)
{
}
int func5(int a,int b)
{
}

可以定义如下指针变量来记录其地址,注意指针变量的类型一定要跟函数匹配。

void (*p1)(void);
int (*p2)(void);
int (*p3)(int);
int (*p4)(int,int);

2、取函数的地址

函数的地址有两种方法获得 &函数名 或者 直接函数名,两种方式等效。

p1 = &func1;
p2 = &func2;
p3 = &func3;
p4 = &func4; 
//以下等效于上面
p1 = func1;
p2 = func2;
p3 = func3;
p4 = func4; 

3、通过指针调用函数

通过指针变量去调用函数,也有两种方式,有* 和没 *都可以。
(1)跟函数调用方式一样,把函数名换成 变量名。
p1();
p2();
p3(1);
p4(1,2);


(2)跟函数调用方式一样,把函数名换成 (*变量名)。
(*p1)();
(*p2)();
(*p3)(1);
(*p4)(1,2);

测试如下代码:

#include <stdio.h>
void func1(void)
{
	printf("this is func1\n");
}
void func2(void)
{
	printf("this is func2\n");
}
int add(int a,int b)
{
	printf("this is add\n");
	return a+b;
}
int sub(int a,int b)
{
	printf("this is sub\n");
	return a-b;
}
int main()
{
	void (*p1)(void);
	int (*p2)(int,int);
	int ret = 0;
	
	p1 = func1;
	p1();
	(*p1)();
	p1 = &func2;
	p1();
	(*p1)();
	
	p2 = add;
	ret = p2(1,2);
	printf("ret = %d\n",ret);
	ret = (*p2)(1,2);
	printf("ret = %d\n",ret);
	
	p2 = &sub;
	ret = p2(1,2);
	printf("ret = %d\n",ret);
	ret = (*p2)(1,2);
	printf("ret = %d\n",ret);
	
	return 0;
}

四、typedef 与函数指针

在以上代码中,函数指针的定义的写法是比较麻烦的,通常我们用typedef 为这种类型取别名。

typedef  void (*type1)(void);
typedef  int (*typ2)(void);
typedef  int (*type3)(int);
typedef  int (*type4)(int,int);

void (*p1)(void);
int  (*p2)(void);
int (*p3)(int);
int (*p4)(int,int);

比较以上两种写法,基本上一样,当有typedef的时候是在定义新的类型。

type1 type2 type3 type4 是类型。
p1,p2,p3,p4 是变量。

type1 p1; //等效于  void (*p1)(void);
type2 p2; //等效于  int (*p1)(void);
type3 p3; //等效于  int (*p3)(int);
type4 p4; //等效于  int (*p4)(int,int);