专栏中心

EEPW首页 > 专栏 > 关于函数指针的使用小结

关于函数指针的使用小结

发布人:mayer 时间:2009-06-01 来源:工程师 发布文章
关于函数指针的使用小结

 

以前学C语言的时候也看过。不过由于用的不多,所以概念也比较模糊,直到这一阵一下子碰到了好几次有关于函数指针的程序。所以花了一些时间仔细研究了一下。

1,定义函数指针:
return_type (*func_pointer)(parameter_list)
例如:int (*p)();
定义一个函数指针p,参数列表为空。
void add()
{
...
}
void main()
{
   void (*p)()=add;
  (*p)(); //执行函数,等效于add();
}

 
2,定义返回函数指针的函数:
return_type(*function(func_parameter_list))(parameter_list)
定义了一个函数function,该函数的参数列表是(function_patameter_list),返回类型是一个函数指针,这个函数指针的原型是return_type(*)(parameter_list)。

例:
int (*add1(int a,int b))(int,int)
此处:此函数的函数主体为add1,add2函数作为add1的形参,返回值为一个函数指针。
注:返回的函数的形式必须为int funcname(int,int)

可以用typedef来简化定义:
//此函数等效于上面函数
typedef int (*funcp)(int)(int); //定义整型函数指针
funcp add1(int a,int b);

 
碰到的一些实例:

1、上电后把存放在Nand flash中的程序复制到内存中以0x30900000开始的地方,之后跳转到相应地址执行程序。
这是阿南的2410开发板的简易bootloader程序。由于Nand flash不能直接运行程序,所以要把程序复制到内存中运行。如下:
#define DOWNLOAD_ADDRESS 0x30900000
void main()
{
      //把程序复制到内存中
      ...
      //跳转到想应地址运行程序
      *((void(*)())(DOWNLOAD_ADDRESS))();
}

分解:DOWNLOAD_ADDRESS为复制的目标地址。
      void(*)() 为函数指针,参数为空。
      (void(*)())DOWNLOAD_ADDRESS 把DOWNLOAD_ADDRESS转为函数指针。
      *((void(*)())(DOWNLOAD_ADDRESS))();    执行相应函数

 

2、实现类似于windows中的回调函数,实现两个数的加法。
int add1(int x,int y)
{
       return x+y;
}
int add(int a,int b, int (* func)(int x,int y))
{
     return (* func)(a,b);
}

调用:
add(3,4,add1);

 

3、一个综合的例子:

#include <stdio.h>
typedef int (*funcp)(int,int);

//普通三个变量的加法函数
int func(int x,int y,int z)
{
// return x+y;
 printf("func:x+y+z=%d\n",x+y+z);
 return x+y+z;
}

/*实现两个数的减法,并返回函数func的地址。此函数的主体为dec(int x,int y),返回值为一个函数指针。注意返回值为函数指针的函数的定义。一开头已经给出。return_type(*function(func_parameter_list))(parameter_list)*/
void (*dec(int x,int y))(int a,int b,int c)
{
 printf("dec:x-y=%d\n",x-y);
 return (void *)func;
}

int add(int x,int y)
{
 return x+y;
}

/*此函数通过回调实现a+b+a+b,并且返回函数add的地址。此函数的主体为add1,add2函数作为add1的形参。返回类型为函数指针。*/
int (*add1(int a,int b,int (*add2)(int x,int y)))(int,int)
{
 printf("add1:a+b+a+b=%d\n",a+b+(*add2)(a,b));
 return add2;
}

/*此函数等效于add2,只不过用typedef进行分开来定义,看的更加清晰。typedef int (*funcp)(int,int); 定义一个函数指针为funcp. funcp add4等同于(*add4)(int,int), funcp add3(int a,int b, (*add4)(int,int)) 等同于 int (*add3(int a,int b,int (*add4)(int x,int y)))(int,int)*/
funcp add3(int a,int b, funcp add4)
{
 printf("add3:a+b+a+b=%d\n",a+b+add4(a,b));
 return add4;
}

 
//函数a1-a5用来验证函数指针数组的功能。
void a1()
{
 printf("this is a1!\n");
}
void a2()
{
 printf("this is a2!\n");
}                                                                        
void a3()
{
        printf("this is a3!\n");
}
void a4()
{
        printf("this is a4!\n");
}
void a5()
{
        printf("this is a5!\n");
}

int main()
{
 int addr;
 //定义函数指针
 int (*p)(int,int,int);
 char i;
 
 //定义函数指针数据,初始化存放a1-a5的函数地址。
 void (*funcarry[5])()={a1,a2,a3,a4,a5};
 int a[5]={(int)a1,(int)a2,(int)a3,(int)a4,(int)a5};

//直接把函数地址转化为整型
 addr=(int)func;

//把函数地址赋给一个函数指针p
 p=func;

//把印出func的地址。
 printf("func address is %d\n",addr);

//利用一个整型的地址来实现3+4+5
 printf("This is addr %d\n",(*((int(*)(int,int,int))addr))(3,4,5));

//利用函数指针来实现3+4+5
 printf("This is func pointer %d\n",(*p)(3,4,5));

//利用dec函数实现5-4,并且打印出返回的函数指针的地址。
 printf("func address is %d %d\n",dec(5,4),addr);

//以下两个功能一致,实现3+4+3+4
 printf("add for add1 address is %d %d\n",add1(3,4,add),(int *)add);
 printf("add for add3 address is %d %d\n",add3(3,4,add),(int *)add);

//利用函数指针数组实现函数a1-a5的执行。以下两种方法等效。
 for(i=0;i<5;i++)
 (*funcarry[i])();


 for(i=0;i<5;i++)
 (*((void(*)())a[i]))();
}

 

运行环境:Red hat 9.0

运行结果:

func address is 134513448
func:x+y+z=12
This is addr 12
func:x+y+z=12
This is func pointer 12
dec:x-y=1
func address is 134513448 134513448
add1:a+b+a+b=14
add for add1 address is 134513529 134513529
add3:a+b+a+b=14
add for add3 address is 134513529 134513529
this is a1!
this is a2!
this is a3!
this is a4!
this is a5!
this is a1!
this is a2!
this is a3!
this is a4!
this is a5!

专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

功率因数校正TRIAC可调光LED驱动器

视频 2011-08-30

CAT24WC128串行E2PROM选型指南

正弦振幅转换器拓扑实现一流的转换效率和功率密度

几个单按钮启停控制程序详解

嵌入式系统 2025-08-01

贸泽推出全新自动化资源中心

机器人、无人机是怎么知道自己的姿态的?揭秘 IMU 的关键参数

机器人 2025-08-01

STM32开发-LL库与HAL库对比

嵌入式系统 2025-08-01

手机无线充电演示

视频 2011-08-25

硬件为什么总背锅

嵌入式系统 2025-08-01

CAT24C64 64Kb串行CMOS EEPROM数据手册(英)

CAT24C32 32Kb串行CMOS EEPROM数据手册(英)

Merifund Capital Management 分析三星与特斯拉的交易

EDA/PCB 2025-08-01

手把手教你在windows上搭建arm汇编开发环境

安森美台灯专用LED照明的参考设计

视频 2011-08-30

驱动LED照明应用--MR16设计挑战

视频 2011-08-30

阿里巴巴推出 Quark AI 眼镜,挑战 Meta 和小米,年底将上市

库克表示,苹果计划“大幅”增加人工智能投资

智能计算 2025-08-01

福布斯:英特尔股价如何跌至10美元

EDA/PCB 2025-08-01
更多 培训课堂
更多 焦点
更多 视频

技术专区