typedef int(init_fnc_t) (void) 和 typedef int(*init_fnc_t) (void)函数类型和函数指针的区别


转载请注明原地址:http://blog.csdn.net/oyhb_1992/article/details/76975284

typedef int(init_fnc_t) (void) typedefint(*init_fnc_t) (void)函数类型和函数指针的区别

函数名概念明确:

       函数名本质就是反汇编后的一个标号。这个标号就指明了函数在内存中的首地址,函数内容就是反汇编后的函数参数传给寄存器或入栈,还可能有一些堆空间的分配,然后是函数的代码段的指令。所以函数名的本质其实是汇编代码的入口地址,调用函数就是movpc,func(函数地址); 所以对函数名(反汇编)内存地址取值*init_fnc_t()是没有意义的。


typedef int(init_fnc_t) (void);

就是对一个 int (void)类型的函数类型进行取别名init_fnc_t。 我们可以利用这个别名进行创建这个类型的函数对象,它的主要功能也就是定义一个函数指针变量:指向一个函数。要明确的是init_fnc_t函数类型是没有什么作用的,它必须init_fnc_t* 才可以用来指向一个init_fnc_t函数类型(参数为空,返回值为int)的变量。

init_fnc_t * init_fnc_ptr;以及指针用来指向一个函数

init_fnc_t ** init_fnc_ptr;二级指针用来指向一个函数指针数组
通俗来讲,函数名是一个地址,而我们调用的时候**()中**也是用地址值。所以我们通常用一个函数指针p指向一个函数名**,调用的时候p()就可以,*p()反倒是错的,前面函数名概念明确里就讲过函数名(反汇编)内存地址取值是没有意义的。

typedef int(*init_fnc_t_p)(void);

这里是一个函数的指针。如果某个函数的类型和这个函数一样的,那么可以将这个函数的指针指向该函数


#include <stdio.h>

int OutData(void)

{

   return 10;

}

int main()

{

   typedef int (init_fnc_t)(void);//函数类型取别名

   typedef int (*init_fnc_t_p)(void);//函数类型指针(地址)取别名

   init_fnc_t *MyFunction;   //定义函数指针变量

   init_fnc_t_p MyFunctionP;   //定义函数指针变量

   MyFunction= OutData;    //函数地址OutData传给MyFunction变量,后面调用的时候//MyFunction()我们也不对这个地址取值

   MyFunctionP = OutData;

   printf("(init_fnc_t)(void) = %d \n",MyFunction());

   printf("(*init_fnc_t_p)(void) = %d \n",MyFunctionP());

   return 0;

}

接下来看一个Uboot里的较复杂的函数指针用法:

 

/************************************************************************

 *Initialize Environment use

 *

 * Weare still running from ROM, so data use is limited

 */

int  env_init(void)

{

         gd->env_addr  = (ulong)&default_environment[0];

         gd->env_valid= 0;

 

         return(0);//返回0代表函数执行成功

}

 

 

typedef int (init_fnc_t)(void);

 

 

/************************************************************************

 *Initialization sequence                                                       *

 ***********************************************************************/

/*定义了函数指针数组,里面数组元素存的是函数地址,调用的时候init_sequence[*] ()就是跳到这个地址处执行函数,* init_sequence[*] ()调用是错误的*/

init_fnc_t*init_sequence[] = {

 

#if defined(CONFIG_BOARD_EARLY_INIT_F)

         board_early_init_f,  /* Call board-specific init code early.*/

#endif

 

         env_init,

         serial_init,

         console_init_f,

         display_options,

         checkcpu,

         checkboard,

         NULL,                          /* Terminate this list*/

};

 

 

void start_armboot (void)

{

         init_fnc_t **init_fnc_ptr;

   /*分成两部分来看init_fnc_t *表示函数指针类型,*init_fnc_ptr 是定义的一个函数指针变量,init_sequence[*] =*init_fnc_ptr 应该相等,都是表示一个函数的内存地址*/

         char*s;

#if defined(CONFIG_VFD) ||defined(CONFIG_LCD)

         unsignedlong addr;

#endif

 

         /*Pointer is writable since we allocated a register for it */

         /*_armboot_start是uboot下载到内存中的地址值,减掉CONFIG_SYS_MALLOC_LEN和gd_t结构体大小就是gd变量的地址*/

   /*为gd指针变量分配内存*/

         gd= (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

         /*compiler optimization barrier needed for GCC >= 3.4 */

         __asm____volatile__("": : :"memory");

    /*清零gd结构体变量的内存*/

         memset((void*)gd, 0, sizeof (gd_t));

          /*注意:内存上gd_t结构体的后面存的是bd_t结构体*/

         gd->bd= (bd_t*)((char*)gd - sizeof(bd_t));

         memset(gd->bd, 0, sizeof (bd_t));

 

         gd->flags|= GD_FLG_RELOC;

   /*_armboot_start=_start*/

         /*得到uboot代码在内存中的存储区域大小*/

         monitor_flash_len= _bss_start - _armboot_start;

 

         for (init_fnc_ptr = init_sequence; *init_fnc_ptr;++init_fnc_ptr) {

                   if ((*init_fnc_ptr)() != 0) {    //*init_fnc_ptr)表示一个函数的地址
						//*init_fnc_ptr==NULL退出循环;++init_fnc_ptr指向下一个数组元素                       				hang ();
                                     /* *init_fnc_ptr是看数组里的成员值是否是NULL,*init_fnc_ptr()中()表示跳到这个函数入口地址处执行函数*/
                   }

         }


什么理解记忆也比不上一张图

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值