[C语言] 【求助】关于函数指针的获取

[复制链接]
2977|15
 楼主| lzp3520265 发表于 2013-9-26 21:03 | 显示全部楼层 |阅读模式
本帖最后由 lzp3520265 于 2013-9-26 21:05 编辑

以51为例
  1. void cc()
  2. {
  3. }
  4. void main()
  5. {
  6.     char ccH,ccL;
  7. }
cc是一个函数指针。
应该是由三个字节组成的:第一个字节是指针的类型。
                        第二个字节是指向函数地址的高8位
                        第三个字节是指向函数地址的低8位
那么如何将函数地址的高8位和低8位赋值给ccH和ccL呢?类似这样。
  1. char *ccP=&cc;
  2. ccH=*(ccP+1);
  3. ccL=*(ccP+2);
但是我希望能直接通过类似这样的方式获取,当然编译通不过。
  1. ccH=cc>>8
  2. ccL=cc>>16
就是说通过编译器直接获取cc的高低地址,而不是通过代码运算。
ayb_ice 发表于 2013-9-27 07:51 | 显示全部楼层
定义一个函数指针变量,然后赋值

void (*pf)(void);

pf  = cc;
q3742829 发表于 2013-9-27 11:22 | 显示全部楼层
过来学习
w522930954 发表于 2013-9-27 15:03 | 显示全部楼层
函数指针不能赋值给char型指针。。
xlsbz 发表于 2013-9-27 22:29 | 显示全部楼层
函数指针 和变量指针本质上 都差不多
xiaoyuan_ly 发表于 2013-10-9 21:49 | 显示全部楼层
"就是说通过编译器直接获取cc的高低地址,而不是通过代码运算 ” 这好像不行吧?! 这样你看行不行,用汇编来解决,找出C编译器cc函数的符号表示直接情况,用汇编来避开C语言规则的安全壁垒,那时的C规则就是浮云了,什么数据类型,你自己随便玩;但好像还是要通过汇编代码的赋值运算了。你看是不是有这个可能? 我只是想了下,没实践过。
xiaoyuan_ly 发表于 2013-10-9 22:06 | 显示全部楼层
想了下,你看这样行不?! 先在C中定义 void cc(void) {} 和 void (* const p)(void) {} , 然后 p = cc; 接着在编译后找出这个p符号在汇编后的符号表示,这时应该是一个函数常量符号(其值就是cc地址),如 _p什么之类的表示,再在你需要的地方嵌入汇编代码。 这样我想应该可以避开C编译器的规则壁垒了吧?!
xiaoyuan_ly 发表于 2013-10-9 22:10 | 显示全部楼层
哦对了,把这2个函数定义成全局外链接的,应该会好找点(找到那个汇编下的符号)。
xiaoyuan_ly 发表于 2013-10-9 22:36 | 显示全部楼层
我刚才翻了下51汇编书,关键是要找到C编译之后,这个函数cc函数名符号在汇编中的表述:如_?cc  那么就可以用这个_?cc直接进行汇编操作。
如下:
_asm
  MOV DPTR,#_?cc
  MOV _?ccH,DPH
  MOV _?ccL,DPL
_endasm
xiongxiaoshuang 发表于 2013-10-9 23:26 | 显示全部楼层
chenbb8 发表于 2013-10-9 23:35 | 显示全部楼层
xiaoyuan_ly 发表于 2013-10-9 22:06
想了下,你看这样行不?! 先在C中定义 void cc(void) {} 和 void (* const p)(void) {} , 然后 p = cc;  ...

不用那么复杂的,直接用union就行了,将值赋给union中的函数指针变量,再当作字节用就OK了。
需要注意的是C51是大端的~

问下C51的函数指针地址是3字节的啊?
STM8倒是可以通过设置更换默认程度的函数指针,或者通过扩展的指令来设置对应函数指针的位数。
64K的STM8必须要选择3字节的才能通过编译。
annwa 发表于 2013-10-10 10:01 | 显示全部楼层
重来没用过函数指针!!
 楼主| lzp3520265 发表于 2013-10-10 19:25 | 显示全部楼层
本帖最后由 lzp3520265 于 2013-10-10 19:31 编辑
chenbb8 发表于 2013-10-9 23:35
不用那么复杂的,直接用union就行了,将值赋给union中的函数指针变量,再当作字节用就OK了。
需要注意的 ...

从keil仿真的结果来看,是三个字节。一个字节表示类型,两个字节表示地址。
现在我发现只要将函数地址转类型赋值给int(16位),就可以得到地址。比如
unsigned char add[2];
void fun(){}
*(int*)add=fun;
这样add[0]是高八位add[1]是低八位。
把指针定义成union还重来没试过,不过感觉貌似很可行啊……
 楼主| lzp3520265 发表于 2013-10-10 19:36 | 显示全部楼层
本帖最后由 lzp3520265 于 2013-10-10 19:37 编辑
xiaoyuan_ly 发表于 2013-10-9 22:36
我刚才翻了下51汇编书,关键是要找到C编译之后,这个函数cc函数名符号在汇编中的表述:如_?cc  那么就可以 ...

恩,类似的方法我试过,是可行的。但虽然我是混编,但是有写地方这样写太不方便。不过C的我也已经解决了。
汇编的可以这样
  1. MOV DPTR,#_?cc
  2. ;或者是
  3. MOV DPH,#HIGH _?cc
  4. MOV DPL,#LOW _?cc
wuzx-61 发表于 2013-10-10 19:58 | 显示全部楼层
chenbb8 发表于 2013-10-10 20:57 | 显示全部楼层
lzp3520265 发表于 2013-10-10 19:25
从keil仿真的结果来看,是三个字节。一个字节表示类型,两个字节表示地址。
现在我发现只要将函数地址转类 ...

试下union咯,你这种强制转换的做法不规范,因为带有隐性转换,可能会有警告。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

41

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部