C++函数指针问题
typedefvoid(*A)(int);typedefvoid(*B)(void*,int);Aa;Bb=*(B*)&a;请问:a和b是怎么转换的?pp(&a,2)为什...
typedef void(* A)(int);
typedef void(* B)(void *, int);
A a;
B b = *(B*)&a;
请问:a和b是怎么转换的?
pp(&a, 2)为什么能进入A的成员函数set()中???
class A
{
public:
void __stdcall set(int a)
{
m_a = a;
}
private:
int m_a;
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
void (__stdcall A::* pSet)(int);
pSet = &A::set;
typedef void (__stdcall * PSET_PROXY)(void *, int);
PSET_PROXY pp = *(PSET_PROXY*)&(pSet);
pp(&a, 2);
return 0;
} 展开
typedef void(* B)(void *, int);
A a;
B b = *(B*)&a;
请问:a和b是怎么转换的?
pp(&a, 2)为什么能进入A的成员函数set()中???
class A
{
public:
void __stdcall set(int a)
{
m_a = a;
}
private:
int m_a;
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
void (__stdcall A::* pSet)(int);
pSet = &A::set;
typedef void (__stdcall * PSET_PROXY)(void *, int);
PSET_PROXY pp = *(PSET_PROXY*)&(pSet);
pp(&a, 2);
return 0;
} 展开
展开全部
typedef void(* A)(int);把A声明为一个函数指针,它所指的函数接收一个int型的参数。
typedef void(* B)(void *, int);把B声明为一个函数指针,它所指的函数接收两个参数,一个为未知类型的参数,一个为int型的参数。
何为指针?指针即为地址。
现在我们假设内存中有两个函数fun1,fun2.
a指针原本是指向函数fun1的。A a=fun1;假设有一个内存地址0x123456,那么这个内存地址存储的内容就是内存中fun1函数的地址。
B b = *(B*)&a;这里的(B*)把a指针的存储地址即0x123456,强制类型转换为B指针。但是转换的是指针指向类型,而不是指针地址也不是指针地址存储的内容。括号前的*再次将指针b指向a的内存地址,也就是0x123456.综合起来说就是,a和b的指针地址即在内存中的存储地址都是一样的,即为0x123456.
说实话,上面是我的分析,我并不是百分百确定,因为我不知道这段代码意义何在。
typedef void(* B)(void *, int);把B声明为一个函数指针,它所指的函数接收两个参数,一个为未知类型的参数,一个为int型的参数。
何为指针?指针即为地址。
现在我们假设内存中有两个函数fun1,fun2.
a指针原本是指向函数fun1的。A a=fun1;假设有一个内存地址0x123456,那么这个内存地址存储的内容就是内存中fun1函数的地址。
B b = *(B*)&a;这里的(B*)把a指针的存储地址即0x123456,强制类型转换为B指针。但是转换的是指针指向类型,而不是指针地址也不是指针地址存储的内容。括号前的*再次将指针b指向a的内存地址,也就是0x123456.综合起来说就是,a和b的指针地址即在内存中的存储地址都是一样的,即为0x123456.
说实话,上面是我的分析,我并不是百分百确定,因为我不知道这段代码意义何在。
追问
从上面代码里发现的问题:
class A
{
public:
void __stdcall set(int a)
{
m_a = a;
}
private:
int m_a;
};
追答
1.成员函数和普通函数最大的区别就是成员函数包含一个隐藏的参数this指针,用来表明成员函数当前作用在那一个对象实例上。根据调用约定(Calling Convention)的不同,成员函数实现this指针的方式也不同。如果使用__thiscall调用约定,那么this指针保存在寄存器ECX中,VC编译器缺省情况下就是这样的。如果是__stdcall或__cdecl调用约定,this指针将通过栈进行传递,且this指针是最后一个被压入栈的参数,相当于编译器在函数的参数列表中最左边增加了一个this参数。
2.
int __stdcall function(int a,int b)
stdcall的调用约定意味着:1)参数从右向左压入堆栈,2)函数自身修改堆栈 3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。
以上述这个函数为例,参数b首先被压栈,然后是参数a,函数调用function(1,2)调用处
翻译成汇编语言将变成:
push 2 第二个参数入栈
push 1 第一个参数入栈
call function 调用参数,注意此时自动把cs:eip入栈。
在这里,你定义了一个函数指针pp,这个pp指向的类A的set函数的。(因为你的pSet是指向set函数的)。当执行pp(&a,2)时:
push 2入栈
push &a入栈
pp调用&a,2,也就是pSet也就是set函数调用&a,2
因为set使用stdcall修饰的,见第1点,传入的时候需要把对象指针传进去。
展开全部
你要是能弄清楚了什么是指针就能明白了。p是指针,首先指的是p是个变量,p有自己的存储地址&p,然后p这个变量存放的是地址。aa是个指针,也有自己的存储位置&aa,aa的值指向一个函数的地址,这个函数就是你定义的那个函数,所以执行p=aa,就是把aa的值赋给p,p=aa执行的是把你所定义的函数地址给了p,所以p也就执行了你定义的那个函数,所以能正常执行。
而p=&aa是什么意思呢,&aa是把存储aa的地址给了p,且不说语法是否正确,这种情况下p的值是个地址,但不是函数的地址,而是aa指针的地址,而问题是aa的值才是函数的地址!!!
而p=&aa是什么意思呢,&aa是把存储aa的地址给了p,且不说语法是否正确,这种情况下p的值是个地址,但不是函数的地址,而是aa指针的地址,而问题是aa的值才是函数的地址!!!
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
首先 计算步骤:
1 取A类型a的地址 &a;
2 将a的地址,转化为B* , (B*)&a;
3 提取B*类型变量地址里面的值*(B*)&a
1 取A类型a的地址 &a;
2 将a的地址,转化为B* , (B*)&a;
3 提取B*类型变量地址里面的值*(B*)&a
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
p=aa就是将aa函数的地址赋值给p了。就像定义一个数组
int
a[10],则a就是这个数组的首地址,而不是&a
int
a[10],则a就是这个数组的首地址,而不是&a
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询