标题:一个宏引发的两个问题(求助)
只看楼主
tanzhou011
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2008-11-15
 问题点数:0 回复次数:10 
一个宏引发的两个问题(求助)
昨天在看别人的代码的时候,看到一个宏,大致的用法是根据结构体的成员地址可以获得结构体的地址,宏具体定义如下:
#define GET_HEAD(type, member, memberaddr) (type *)(void *)(memberaddr - (int) ((type *)0)->member),意思我大概看懂了,就是根据结构体成员跟结构体头的地址偏移量一定来得到结论。但是由此也引发了两个问题:
1.为何类型转换的时候要使用(void *),而不是直接转换成type?强制转换成void一般在何种场合下使用?
2.(type *)0->member的含义,既然是0地址,应该就代表NULL,一个指向NULL的结构体指针取成员,C语言应该是不允许的吧,但是如果把0看成起始地址为0的话,又说得过去。也就是说,在为指针分配内存的时候是不可能分配0这个地址的,那么一般是从哪个地址开始分配呢?
小弟比较迷惑,如有大侠解答,不胜感激
搜索更多相关主题的帖子: 结构体 member void 
2008-11-15 23:45
tanzhou011
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2008-11-15
得分:0 
怎么没人回啊。。。先顶一下
2008-11-16 10:14
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
得分:0 
- -今天刚刚在代码中用到了……这个用在C语言里面,可以模拟C++的向上转型……
2008-11-16 15:01
forever74
Rank: 12Rank: 12Rank: 12
来 自:CC
等 级:贵宾
威 望:49
帖 子:1636
专家分:3940
注 册:2007-12-27
得分:0 
我怀疑这样写语法上会被警告
退一步说,语义上似乎缺少一个&

对宇宙最严谨的描述应该就是宇宙其实是不严谨的
2008-11-16 15:12
ntmdgbhwdmm
Rank: 1
等 级:新手上路
帖 子:21
专家分:0
注 册:2008-11-16
得分:0 
up
等待解答
2008-11-16 15:16
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
得分:0 
我用的是:
#define GET_PARENT(ptype, field, member) \
    (ptype)((char*)(member) - (char*)&(((ptype)(void*)0)->field))

没有转到int,因为怕64位机会不兼容。
使用的时候直接GET_PARENT(struct stu*, link, pt)
2008-11-16 15:25
forever74
Rank: 12Rank: 12Rank: 12
来 自:CC
等 级:贵宾
威 望:49
帖 子:1636
专家分:3940
注 册:2007-12-27
得分:0 
是啊,6楼的至少比LZ的多个&
这样在语义上就能理解了

对宇宙最严谨的描述应该就是宇宙其实是不严谨的
2008-11-16 15:30
forever74
Rank: 12Rank: 12Rank: 12
来 自:CC
等 级:贵宾
威 望:49
帖 子:1636
专家分:3940
注 册:2007-12-27
得分:0 
如果LZ的问题也是这个意思的话
那么:
1、LZ的(void *)放错了位置,应该放在它右边的左括号的里边,也就是...(type *)((void *)memberaddr-...,用来保证指针运算是以字节为单位的。

2、没有一般。代码和数据放在什么地址由编译器说了算,只要能让操作系统找到的地方就可以。也就是说不同的编译器会按照自己的方式把它们放到不同的地方。
唯一由C规定不能放的地方就是0。当然操作系统和编译器还会规定其他不能放的地址,但这就和C语言标准无关了。

对宇宙最严谨的描述应该就是宇宙其实是不严谨的
2008-11-16 15:41
tanzhou011
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2008-11-15
得分:0 
获益匪浅啊,还想问一下:6L的(((ptype)(void*)0)->field)),为什么不直接使用((ptype *)0)->field)?还有既然0地址无法使用,这样用会不会报错或者有危险?
2008-11-16 16:01
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
得分:0 
[bo][un]forever74[/un] 在 2008-11-16 15:41 的发言:[/bo]

如果LZ的问题也是这个意思的话
那么:
1、LZ的(void *)放错了位置,应该放在它右边的左括号的里边,也就是...(type *)((void *)memberaddr-...,用来保证指针运算是以字节为单位的。

2、没有一般。代码和数据放 ...


哦…………我习惯写char*,因为老是觉得void*是没有大小信息的,所以不允许相减……

不过这是错误的观点,C语言中void*的步进为一,只是在C++中不允许void*相减……

不管怎么说,还是写char*比较安全——对我而言……
2008-11-16 16:20



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-244518-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016617 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved