请解释一下这个代码?

cba_v 2008-11-08 08:02:14
#include <stdio.h> 
long becall(long a)
{
return (*((long*)(&a-1)));
}
void work(int a)
{
if(a>1000)exit(0);
printf("%d\n",a);
}
int main(void)
{
int a=0;
long addr;
void(*pf)(void);
addr=becall(0);
work(a++);
pf=(void(*)(void))addr; // 这个是强制 转换成函数指针吗?
(*pf)(); //调用的是什么啊?
return -1;
}

在论坛 上 看到的
becall函数的中的 return (*((long*)(&a-1))); 没有 看懂是怎么回事 能否讲解一下 谢谢了
...全文
107 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
gaohoalianga 2008-11-09
  • 打赏
  • 举报
回复
不懂的
xiangxuf 2008-11-09
  • 打赏
  • 举报
回复
2楼讲的清明透底!
nhycf 2008-11-09
  • 打赏
  • 举报
回复
我想补充一点:
此代码还隐含了"调用函数返回过程与4字节参数弹出过程"巧妙地契合.因此不会造成堆栈上溢.
nhycf 2008-11-09
  • 打赏
  • 举报
回复
传任意long值都可以的

/*
return (&a)[-1]; 如下图:
-4 0 4
ip a

你可以把&a看做是一个long数组的起始位置
(&a)[0]也就是得到a的值
(&a)[-1]就是得到ip的值
*/
cba_v 2008-11-09
  • 打赏
  • 举报
回复
谢谢2楼 的讲解 不好意思 还是 不太明白
return (&a)[-1]; 没看懂 返回的 (&a)[-1] 是什么意思?
addr=becall(0); 为什么要要传0啊?
herman~~ 2008-11-08
  • 打赏
  • 举报
回复
mark
nhycf 2008-11-08
  • 打赏
  • 举报
回复
其实可以写成这样:

#include <stdio.h>
long becall(long a)
{
return (&a)[-1];
}
void work(int a)
{
if(a>1000)
exit(0);
printf("%d\n",a);
}
int main(void)
{
int a=0;
long addr;
void(*pf)(void);
addr=becall(0);
//lbl_loop:
work(a++);
pf=(void(*)(void))addr; // 这个是强制 转换成函数指针吗?
(*pf)(); //调用的是什么啊?
return -1;
}


返回的是调用becall()返回后,马上要执行的点,也就是下一句:work(a++); (虽然严格来说并不是)
因此执行(*pf)()就相当于goto lbl_loop;


原因:
依据C的调用规则,先压参数a,再压入下一eip。因此long a所处的堆栈的上4个字节是返回地址

例如:
long a位于0x0012FF24
0x0012ff20就存放着 从becall返回后马上就要执行的点,也就是work(a++);
lxl_2008 2008-11-08
  • 打赏
  • 举报
回复
我刚刚在VC6.0下调试运行了一下,addr=becall(0);到(*pf)(); 之间是循环运行的,程序由exit(0);
处退出。return (*((long*)(&a-1)))的作用是返回内存存放a的地址的4个字节(即一个long型)的内容。
但不明白这样写有什么意义!

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧