请问这个指针为什么这么定义?#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))这个为什么把p变为二级指针又变回一级指针,它跟下面的有区别吗?#define AEEGETPVTBL(p,iname) (((AEEVTBL(iname) *)((void *)p

来源:学生作业帮助网 编辑:作业帮 时间:2024/05/03 11:12:32
请问这个指针为什么这么定义?#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))这个为什么把p变为二级指针又变回一级指针,它跟下面的有区别吗?#define AEEGETPVTBL(p,iname) (((AEEVTBL(iname) *)((void *)p

请问这个指针为什么这么定义?#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))这个为什么把p变为二级指针又变回一级指针,它跟下面的有区别吗?#define AEEGETPVTBL(p,iname) (((AEEVTBL(iname) *)((void *)p
请问这个指针为什么这么定义?
#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))
这个为什么把p变为二级指针又变回一级指针,它跟下面的有区别吗?
#define AEEGETPVTBL(p,iname) (((AEEVTBL(iname) *)((void *)p)))
还有在程序中经常有这样的强制转换:(TypeName*)(void*)p
为什么中间要有一个void先转换一下?
请问无论二级还是多级指针都可以转化为void

请问这个指针为什么这么定义?#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))这个为什么把p变为二级指针又变回一级指针,它跟下面的有区别吗?#define AEEGETPVTBL(p,iname) (((AEEVTBL(iname) *)((void *)p
区别大着呢
首先,你必须搞明白这个宏是做什么用的,我给你详细讲一下:
1) 最外层的*,说明这是一个取“指针指向地址内容”的操作,比如int a; int *p=&a; int c=*p;最后一句*p就是取p所指向地址的内容,这里p指向a(p存了a的地址).先不管那一堆括号,可以这样缩写来看,#define AEEGETPVTBL(p,iname) (*((暂时忽略)p)),也就是取出p的内容,至于p的类型,下面说明.从这个意义上来说,你给的另一个写法完全是另一回事,#define AEEGETPVTBL(p,iname) ((((暂时忽略)p))),它返回的是p本身,而不是其内容
1补充) 我假定你明白这样的宏代表什么意思,简单理解就是类似于定义一种函数,只不过在编译阶段特殊处理
类似例子:
int a;
int *p = &a;
int **pp = &p;
*((int **)(void* pp));//正确
(int *)(void* pp);//有问题
2) 我们再来看忽略的部分:((AEEVTBL(iname) **)((void *)p))
AEEVTBL(iname):
其原型为#define AEEVTBL(iname) iname##Vtbl,就是返回一个源代码字符串(注意不是"abcd"这样的字符串),比如这样的代码AEEVTBL(haha) i;相当于hahaVtbl i;它把iname当作一种可变字符串和Vtbl连接起来,这样你就可以用编译期可变的类型来写代码了(不理解也没关系,就是返回一种类型)
那么也就是说这里代表一种类型,和iname有关,为了理解,我们假定为type
(void *)p:
很简单,把p转换为void*类型,这是一种不带类型信息的指针,我们假定为vp
((AEEVTBL(iname) **)((void *)p)) 化简为 ((type **)vp)
#define AEEGETPVTBL(p,iname) (*((AEEVTBL(iname) **)((void *)p)))化简为#define AEEGETPVTBL(p,iname) (*((type **)vp))
串起来就是,先把p强制转换为void*,然后再强制转换为type**,最后取出其地址内容,而你的另一个不是这样的
最后,解释一下void转换问题
任何类型的指针,包括0,都可以隐式的转换为void*,隐式的意思就是说,有这么个函数void f(void*),你传入任何类型的指针都是可以的,编译器会自动帮你先转为void*.在你的代码里,如果去掉void*,也不会出错,因为强制转换(TypeName*)p就好比那个接受void*的函数,会进行隐式转换.但是为什么这样写呢?一般说来,编译器背地里做的事可能会带来某些未知的影响,而且也不便于代码阅读,这样写是一种好的代码习惯.