原创 关于函数指针的使用小结

2009-5-27 19:26 4808 11 11 分类: MCU/ 嵌入式

以前学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)();



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


 


运行环境: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!


 

文章评论0条评论)

登录后参与讨论
相关推荐阅读
colinluan_500799913 2011-12-16 15:23
MIPS 是什么意思? MIPS/MHZ 又是什么意思?
MIPS ( Million Instruction Per Second )表示每秒多少百万条指令,如 10MIPS ,表示每秒一千万条指令。MIPS/MHz 表示 CPU 在每 MHz 的运行...
colinluan_500799913 2011-11-23 16:41
APN是什么
对普通用户来说,使用GPRS上网,几乎都要遇到APN 这个概念, 其实,APN就是一个接入点,GPRS上网的接入服务器 ; 一、 APN的概念 APN(Access Poin...
colinluan_500799913 2009-06-20 18:01
MMU工作原理
1.MMU的工作原理我这里就不阐述了。网上有篇关于S3C2410 MMU的讲解,很详细。我就看了韦东山大哥的书的实验代码就写一些体会,并把源代码发出来。具体的代码如下:////////////////...
colinluan_500799913 2009-06-17 13:49
基于ARM9芯片S3C2410异常中断程序设计
验证的代码详细分析了基于ARM嵌入式系统的异常处理流程。然后阐明关键字“-irq”的作用,设计出中断处理函数。最后,通过设置中断控制寄存器,设计外部中断EINT3的初始化程序,并给出主程序流程图。实践...
colinluan_500799913 2009-06-13 15:15
linux下ntp协议的实现
最近公司比较空,花了一些时间学习了一下linux的应用编程,并且在今天下午完成了最后一章socket的实验。内容就是实现ntp协议,使本机的时间与ntp服务器同步。虽然说原理上并不难,但是过程中却也遇...
colinluan_500799913 2009-06-02 16:39
ubuntu下安装vmware tools
如果你是在VM下安装 Ubuntu,那么必须安装VMware-tools,才能获得更好的体验,包括屏幕分辨率、声音、和windows共享剪贴板等等。点击VMware菜单的-VM-Install VMw...
我要评论
0
11
1
2
3
4
5
6
7
8
9
0
关闭 热点推荐上一条 /4 下一条