一、开始

在阅读代码的时候看到有一段代码,令人有点懵。

static void __near VECTOR_TABLE_04H(void){((void(*)(void))(*(__far unsigned long *)(FLASH_TABLE + 0x04 *2)))();}

看上去像是一个函数,调整一下位置,括号太多了。

static void __near VECTOR_TABLE_04H(void)
{(   ( void(*)(void) )   (*(__far unsigned long *)(FLASH_TABLE + 0x04 *2))     )    ();
}

__far与__near都是与编译器有关的参数,可以忽略。

首先看:( * (__far unsigned long *)(FLASH_TABLE + 0x04 *2))
这是单片机里常用的方式,先将一个值强制转化为unsigned long类型指针,再用 * 取值。

然后: void(*)(void)是函数指针,返回void,参数void。即把取出的值强制转化为函数指针。

最后:() ,就是起到调用函数的作用了。

二、而有的函数指针比较特殊

如int ( * )()或void ( * )()。可以使用任何函数类型,即未指明参数、返回int或void的函数作为通用函数指针。

测试代码
使用:chcp查看cmd的编码,936代码gbk。(可以使用命令:chcp 65001,暂时切换为UTF-8编码 )

注意:gcc编译的时候,后面加上-fexec-charset=gbk,不然可能中文打印乱码

#include <stdio.h>
#include <stdlib.h>void myfunc_void_void(void){ printf("This is myfunc_void_void\n");};
void myfunc_void_int(int t){printf("This is myfunc_void_int,input:%d\n",t);};
int myfunc_int_void(void){ printf("This is myfunc_int_void\n");}
int myfunc_int_int(int t){ printf("This is myfunc_int_int,input: %d\n",t);}void myfunc_void_generalPointer(void* t){printf("myfunc_void_generalPointer:is a int:%d \n",*(int*)t);
printf("myfunc_void_generalPointer:is a char:%c \n",*(char*)t);
//printf("func3:is a string:%s ?\n",(char*)t);
};typedef void(*pointer_2_void_func_void)(void);
typedef void(*pointer_2_void_func_int)(int);typedef int(*pointer_2_int_func_void)(void);
typedef int(*pointer_2_int_func_int)(int);typedef void(*pointer_2_void_func_general)();
typedef int(*pointer_2_int_func_general)();int main(int argc,char** argv){//取指针地址为值,再转换回去。printf("//取指针地址为值,再转换回去:\n");int value_func_address = (int)myfunc_void_void;pointer_2_void_func_void  p1  = ( void ( * )(void) ) value_func_address;p1();//用直接的方法,声明一个void通用函数指针printf("//用直接的方法,声明一个void通用函数指针:\n");void ( *gpv0 )() ;gpv0 = myfunc_void_void;gpv0();gpv0 = myfunc_void_int;gpv0(998);/*error example 错误例子pointer_2_int_func_void int_void_p1;pointer_2_int_func_int  int_int_p2;int_void_p1 = myfunc_int_int;int_int_p2  = myfunc_int_void;*///用通用函数指针定义,void和int类型通用函数指针printf("//用通用函数指针定义,void和int类型通用函数指针:\n");pointer_2_void_func_general  gvp1;pointer_2_int_func_general   gip1;gvp1 = myfunc_void_void;gvp1(); int ts = 15;gvp1 = myfunc_void_generalPointer;gvp1(&ts);gip1 = myfunc_int_void;gip1();gip1 = myfunc_int_int;gip1(45);//函数参数是void*类型时:printf("//函数参数是void*类型时:\n");int a=14;char b='g';char* c="abs";myfunc_void_generalPointer(&a);myfunc_void_generalPointer(&b);//myfunc_void_generalPointer(c);return 0;
}

输出如图:

三、参考书籍

第四章-指针-4.13
问:通用指针类型是什么?当我把函数指针赋向void *类型的时候,编译通不过。
答:没有什么“通用指针类型”。void 指针只能保存对象(也就是数据)指针。将函数指针转换为void 指针是不可移植的。(在某些机器上,函数指针可能很大—–比任何数据指针都大。)但是,可以确保的是,所有的函数指针类型都可以相互转换,只要在调用之前转回了正确的类型即可。因此,可以使用任何函数类型(通常是int ()()或void ()(),即未指明参数、返回int或void的函数)作为通用函数指针。如果你需要一个既能容纳对象指针又能容纳函数指针的地方,可移植的解决方案是使用包含void *指针和通用函数指针(任何类型都可以)的联合。

第四章-指针-4.14
问:怎样在整型和指针之间进行转换?能否暂时把整数放入指针变量中,或者相反?
答:曾经有一段时间,可以确保能将指针转换为整数(尽管谁也不知道究竟是需要int还是long型),将整数转换为指针。同时可以确保指针在转换为(足够大的)整数及转换回来的时候值不会改变,而且转换(及任何映射)都不应该“让那些知道机器寻址结构的人感到惊奇”。换言之,有整数/指针转换的先例和支持,但这总是和机器相关的,因此不具可移植性。
而且总是需要显式的类型转换(但是就算你忘了转换,早期的编译器也几乎不会报警。)为了使C语言广泛地可实现,ANSI/ISO C标准削弱了这些早期的保证。指针到整数和整数到指针的转换变成了实现定义的(参见问题11.35),因此也就没有了指针和整数可以无需修改就相互转换的保证。
强制将指针转换为整数和将整数转换为指针从来都不是什么好的实践。当需要同时保存两种类型数据的存储结构的时候,使用联合是一个更好的办法。

更新:
书籍信息:《C Programming FAQs: Frequently Asked Questions》、《你必须知道的495个C语言问题(这中文翻译名称完全对不上,让人好找。。。)》 作者: Steve Summit 时间:1996
。。====
本书有网页版:https://c-faq.com/index.html

C语言-函数指针void(*)(void),通用函数指针void(*)()相关推荐

  1. c语言函数的数组返回和指针返回

    函数内的数组和指针都是属于函数栈空间.如果把数组或指针返回给外部指针,会发生什么? 1先看看第一种,返回数组: #include "stdio.h"char * get_c() { ...

  2. c语言 万能函数指针,C/C++编程笔记:C语言精华解析之void *指针,指针中的万能指针...

    什么是万能指针? 万能指针其实就是void *类型的指针,而void *指针一般被称为通用指针或叫泛指针.它是C语言关于纯粹地址的一种约定.当某个指针是void型指针时,所指向的对象不属于任何类型. ...

  3. 虚函数指针sizeof不为sizeof(void*)

    ref:http://bbs.csdn.net/topics/360249561 一个继承了两个虚基类又增加了自己的一个虚函数pif的类,sizeof(指向pif的指针)竟然是8(X86). 我是从这 ...

  4. C语言 void和void *(无类型指针)

    void 关键字 void的字面意思是"无类型",void *则为"无类型指针",void *可以指向任何类型的数据. void几乎只有"注释&quo ...

  5. c语言 void**类型转换,void *和其他指针的转化

    ==1===在c语言中=============== 从int * 到 char *的转化不兼容,但是编译能通过. 将void *和其他类型的指针相互赋值不出现警告,这在c语言中是允许的. ===== ...

  6. 函数指针的强制类型转换与void指针

    前两天在移植一个DVB芯片的驱动库时,遇到一个情况: 驱动库的作者为了使DVB芯片兼容尽可能多的tuner芯片,在定义tuner_init函数指针时,参数中的handle定义为(void* handl ...

  7. 搬砖:void (*signal(int sinno,void(*func)(int)))(int) 函数指针

    函数名做函数参数 2008年03月04日 23:40:00 crfoxzl https://blog.csdn.net/crfoxzl/article/details/2147744 void (*f ...

  8. C语言-指针-基础用法、运算、指针与数组、指针数组、多级指针、void指针和const修饰符-学习笔记08

    文章目录 1. 地址和变量 2. 指针 2.1 基本声明 2.2 指针的目标 3. 指针的运算 3.1 指针的赋值运算 3.2 指针的算术运算 3.2.1 指针与常量的加法与减法 3.2.2 两指针相 ...

  9. 一级指针和二级指以及(void**)在双链表中的应用

    因为函数参数是按值传递的,所以要想改变变量,必须传递地址. 二级指针实际上就是指针变量的地址,如果传递二级指针,函数声明必须写**. (void**)&必须是本质上就是指针变量的地址才可以做这 ...

最新文章

  1. Android WebView与ViewPager的滑动冲突分析
  2. 设置文件权限位时我们一般忽略了suid/guid的存在,现在看看它们到底是怎么回事
  3. 轮播swiper配置选项
  4. python运行不了、显示警告_Python中偶尔遇到的细节疑问(二):UnicodeDecodeError,警告与忽略警告warnings...
  5. C++ iterator迭代器
  6. [转载] java注释
  7. 史上最快AI计算机发布!谷歌TPU V3的1/5功耗、1/30体积,首台实体机已交付
  8. 指针的指针指向指针数组的指针
  9. 在Ubuntu 18.04上安装MongoDB
  10. PeekMessage和GetMessage的区别
  11. 7-24 说反话-加强版 (20 分)
  12. 人工智能应用-手把手教你用Python硬件编程实现打开或关闭电灯泡
  13. 电影社交网络中Facemash女生评比算法Java实现
  14. ls只显示文件名/只显示文件夹名
  15. 零基础入门学习Python(31)--永久存储:腌制一缸美味的泡菜
  16. 【木头Cocos2d-x 026】Lua篇(第01章):让Lua和C++牵手
  17. 牛津花卉数据集(Oxford 17/Oxford 102)官网
  18. 2014年注电考试心得
  19. C# Web Mvc 企业微信 回调
  20. 对话图灵奖得主Jeffrey Ullman:数据库不会进入周期性的坏循环|《新程序员》

热门文章

  1. python自动化输入文本_python输入文本
  2. 计算机专业大一期末总结
  3. 收入--支出=储蓄?
  4. 5_echo命令的作用
  5. Angular NG-ZORRO 解决 nz-table 加纵向滚动条表头和单元格不对齐的问题
  6. RxJava-Introduction
  7. luogu P3642 [APIO2016]烟火表演
  8. 最终幻想-核心危机中魔石融合附全能力详细教学
  9. 危机公关处理流程及成功案例解读
  10. php标题行,php 显示标题