请问这个指针为什么这么定义?
来源:学生作业帮 编辑:神马作文网作业帮 分类:综合作业 时间:2024/11/11 15:53:04
请问这个指针为什么这么定义?
#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)))
还有在程序中经常有这样的强制转换:(TypeName*)(void*)p
为什么中间要有一个void先转换一下?
请问无论二级还是多级指针都可以转化为void
区别大着呢
首先,你必须搞明白这个宏是做什么用的,我给你详细讲一下:
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*的函数,会进行隐式转换.但是为什么这样写呢?一般说来,编译器背地里做的事可能会带来某些未知的影响,而且也不便于代码阅读,这样写是一种好的代码习惯.
再问: 谢谢了!您解释的好详细啊,请问无论二级还是多级指针都可以转化为void *类型吗?在vc里语法上没有报错 另外这个程序为什么还是返回地址,而不是一个ASC码值呢 #include main() { char a='c'; char *pchar = &a; char **ppchar = &pchar; int *i = *((int **)(void *)ppchar); printf("%d\n",*i); }
再答: 1. 指针也是一种变量,只不过它专门存储内存地址,具有固定长度,一般为32位或者64位,无论一级还是多级指针都是这样。而void*是一种特殊的指针,任何指针类型都可以转换为void*,无论几级的。 2. 要用printf输出十六进制数字,要用%x或者%X或者%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*的函数,会进行隐式转换.但是为什么这样写呢?一般说来,编译器背地里做的事可能会带来某些未知的影响,而且也不便于代码阅读,这样写是一种好的代码习惯.
再问: 谢谢了!您解释的好详细啊,请问无论二级还是多级指针都可以转化为void *类型吗?在vc里语法上没有报错 另外这个程序为什么还是返回地址,而不是一个ASC码值呢 #include main() { char a='c'; char *pchar = &a; char **ppchar = &pchar; int *i = *((int **)(void *)ppchar); printf("%d\n",*i); }
再答: 1. 指针也是一种变量,只不过它专门存储内存地址,具有固定长度,一般为32位或者64位,无论一级还是多级指针都是这样。而void*是一种特殊的指针,任何指针类型都可以转换为void*,无论几级的。 2. 要用printf输出十六进制数字,要用%x或者%X或者%p