Chinaunix首页 | 论坛 | 博客
  • 博客访问: 344827
  • 博文数量: 46
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 562
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-14 13:32
个人简介

先知者为师

文章分类

全部博文(46)

文章存档

2016年(1)

2015年(6)

2014年(20)

2013年(19)

我的朋友

分类: LINUX

2014-03-09 21:23:16

函数指针的定义相比大家都知道,返回值是函数指针的也有相关说明,比如linux下的信号处理函数signal()这个函数的原型就不贴出来了
因为这不是本篇文章的重点,本篇文章的重点是在返回值是函数指针的用法 普通的用法大家应该都见过,先来个引子热热身:
废话不多说先上代码

点击(此处)折叠或打开

  1. #include <stdio.h>

  2. typedef int(*rtfunc_t)(int );

  3. int foo(int m)
  4. {
  5.     printf("m = %d\n",m);
  6.     return 0;
  7. }

  8. rtfunc_t func(int a)
  9. {
  10.     return foo;
  11. }

  12. int main(int argc, const char *argv[])
  13. {
  14.     func(1)(2);

  15.     return 0;
  16. }
运行结果是m=2;
注意第18行的用法,这个用法可能比较少见,第一个参数素传给func函数的,第二个参数素传个函数指针的
可能有不少人见过这种用法,但是原理是怎样的就不得而知了。
一般情况下unix下c程序调用函数是参数入栈,想当然的情况是
pushl 1
pushl 2
call func;
但是这样的话想想函数执行的原理也是想不通的当执行foo函数的时候其参数到底在什么位置,
对于func函数来说在(ebp+8)的位置,但是对于foo来说呢 因为foo也是函数 也有自己的栈帧
其参数肯定不会在(ebp+8)的位置、
我们来看下汇编代码(在linux执行gcc -S 就可以得到其汇编代码)

点击(此处)折叠或打开

  1. main:
  2. .LFB2:
  3.     .cfi_startproc
  4.     pushl    %ebp
  5.     .cfi_def_cfa_offset 8
  6.     .cfi_offset 5, -8
  7.     movl    %esp, %ebp
  8.     .cfi_def_cfa_register 5
  9.     andl    $-16, %esp
  10.     subl    $16, %esp
  11.     movl    $1, (%esp)
  12.     call    func
  13.     movl    $2, (%esp)
  14.     call    *%eax
  15.     movl    $0, %eax
  16.     leave
  17.     .cfi_restore 5
  18.     .cfi_def_cfa 4, 4
  19.     ret
  20.     .cfi_endproc
此处只贴上相关的代码
注意第11行12行 在call func函数之前只是把1入栈 调用完毕再把数字2入栈 然后再call eax 此刻的eax 值是 foo的地址
从这里可知,只有遇到函数的时候才会把自己的参数入栈 也就是创建自己的栈帧,不会和其他函数冲突。





阅读(1722) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~