转载请注明原地址: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.*/#endifenv_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()中()表示跳到这个函数入口地址处执行函数*/}}

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

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

  1. 使用typedef语句定义函数类型和函数指针

    首先我们要先明白一个概念,函数名是不是指针?也就是说一个函数名可不可以代表一个地址?以及什么是函数类型? 经过查找,函数名就是一个指针,但是意义是不一样的,如同于数组a[],a和&a其实都是一 ...

  2. typedef 函数类型 详解

    本博客以后只出精品,一篇博客可能需要诸多次改进才能完成,希望大家可以提出有效的建议. 首先需要搞清楚三个概念: 函数: 一个函数包括,函数名,返回值,参数列表. 那么函数名在C 语言中,表示什么呢? ...

  3. Java LinkedList void add(int index,Object o)方法,带示例

    LinkedList void add(int index,Object o)方法 (LinkedList void add(int index, Object o) method) This met ...

  4. 13.请编一个函数void fun(int tt[M][N],int pp[N]),tt指向一个M行N列的二维数组,求出二维数组每列中最小元素,并依次放入pp所指一维数组中。

    13.请编一个函数void fun(int tt[M][N],int pp[N]),tt指向一个M行N列的二维数组,求出二维数组每列中最小元素,并依次放入pp所指一维数组中.二维数组中的数已在主函数中 ...

  5. C语言中void cpy,关于C/C++ void指针,使用void指针拷贝int 数组

    在C/C++中void代表的就是无类型或者为空,作为void *p这样的定义则说明这个指针 只包含了指针位置而不包含指针的类型,一般的指针包含2个属性指针位置和类型, 其中类型就能判断出其长度. 借用 ...

  6. 【c语言】unresolved external symbol void __cdecl print(int * const,int) (?print@@YAXQAHH@Z)

    前言:在写折半排序的时候,出了一个错误,找了一下,终于发现问题了. 程序中我自定了函数,又引用了stdio.h文件,所以一直保证错误 #include<stdio.h> #define N ...

  7. C语言中void fun() 与 int fun()的区别

    一.指代不同 1.void fun() :定义一个空返回值的fun函数. 2.int fun():定义一个返回整数型的fun函数. 二.用法不同 1.void fun() :可以直接调用fun函数. ...

  8. void main和int main的区别

    其实main也是一个函数: #include<stdio.h> void main(){ } 如上代码所示,void main() 这样定义只是说明main函数没有返回值. #includ ...

  9. C/C++中“int main()”和“int main(void)”的区别

        考虑main()的以下两个定义. int main() {/* */ return 0; }     和 int main(void) {/* */ return 0; }     有什么区别 ...

最新文章

  1. GSS-API GSSAPI 介绍 通用的安全机制
  2. 如何让产品不受到技术限制快速迭代?
  3. Oracle442个应用场景-----------Oracle数据库物理结构
  4. .NET开发作业调度(job scheduling) - Quartz.NET
  5. Promise实战AJAX封装
  6. SPP-net论文笔记
  7. 小a与星际探索---DP
  8. AndroidStudio安卓原生开发_Activity_中Activity显示/隐式启动Action和Category配置详解---Android原生开发工作笔记84
  9. Python办公自动化(七)|自动更新不对称表格
  10. Struts2 中 Session 的使用
  11. 网络切片技术缺点_5G中网络切片研究的现状与挑战
  12. Doc2Vec 模型参数
  13. mybatis plus 生成代码 保存方法主键报错 nested exception is org.apache.ibatis.reflection.ReflectionException: Cou
  14. 计算股票收盘价的月日均值 matplotlib绘图
  15. poi word表格系列操作
  16. 一个无经验的大学毕业生,可以转行做软件测试吗?我的真实案例
  17. 550+集Java学习全套视频课程,新手入门收藏
  18. MATLAB弹出对话框的使用
  19. Linux通过脚本实现远程自动备份
  20. 防火墙控制Docker端口开放与关闭

热门文章

  1. photoshop---阈值磨皮去斑
  2. 解决Word中MathType公式与文字对齐问题
  3. linux操作系统定制的目的是,Linux操作系统在定制PMP DM320的应用解析
  4. 创建一个矩形类的子类——正方形类,类中定义求面积方法、重写求周长的方法.在主类中,输入一个正方形边长,创建正方形对象,求正方形的面积和周长
  5. mybase和mysql_mybase 用户教程
  6. QtTableWidget左上角全选按钮添加信号槽
  7. python手动实现图像像素的kmeans聚类(附代码)
  8. 图的深度遍历 (邻接矩阵)
  9. 小程序中图片宽度实现100%,高度自适应
  10. 一文搞懂二叉树遍历---超详解(二叉树逐步剖析二)