这代码是参照别人的文章写的,只供自己理解用,有兴趣的也可以看看。
地址:http://eulertao.ycool.com/post.1762422.html
#include <cstdlib>
#include <iostream>
using namespace std;
#define offset(type,member) ((int)&(((type*)0)->member))
/*
即假设0地址是s类型的一个实例,则成员变量m的地址应该是?
应为起始地址是0,所以求出的地址也就可以直接看作是偏移量
*/
typedef void func(char *);
typedef struct mystu
{
char * str;
func * f;
}mystu_t;
void print(char * str)
{
printf("[%s]\n",str);
}
int main(int argc, char *argv[])
{
mystu_t t;
t.str="This is a expriment";
t.f=print;
int offs=offset(mystu_t,f);
printf("&t=0x%x &t.f=0x%x offset=%d t.f=0x%x &print=0x%x\n",&t,&t.f,offs,t.f,&print);
//t.f是函数在内存的实际地址,而&(t.f)是t中保存这个函数地址的地址。
/*
&t-------> -------------- 地址 -->0x22ff70 在我编译平台&t为:0x22ff70
| char* |内容 -->"This is a expriment"
&t.f-----> -------------- 地址 -->0x22ff74 在我编译平台&t.f为:0x22ff74
| func* |内容 -->0x401390 是t.f(print)的实际地址,在我编译平台t.f为:0x401390
--------------
*/
func * f1=*(func**)(((int)&t)+offs);//t+offs是t.f的地址,那就是func * 的地址 ,int起以转值的作用
/*
&t-----------------> -------------- 地址 -->0x22ff70 在我编译平台&t为:0x22ff70
| char* |内容 -->"This is a expriment"
((int)&t)+offs-----> -------------- 地址 -->0x22ff74 在我编译平台&t.f为:0x22ff74
| func* |内容 -->0x401390 是t.f(print)的实际地址,在我编译平台t.f为:0x401390
--------------
可以看出 ((int)&t)+offs就是保存print地址的地址,但编译器不能直接用*对它取值,
我们知道了它是print地址的地址后,就可以将它强制转换成func **,然后对它取值,就是func *
*/
printf("real func addr = 0x%x\n", f1);
f1(t.str);
system("PAUSE");
return EXIT_SUCCESS;
}
文件在这里,下载来看比较清楚:
代码文件