offsetof()宏 [英] offsetof( ) macro

查看:106
本文介绍了offsetof()宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

offsetof(T,m)(size_t)&(((T *)0) - > m)


为什么我们总是从这个宏的0开始访问

结构或联合的偏移量。标准保证结构和联合

是否位于地址0?如果是,那么如果我有两个或更多

结构怎么办?他们怎么能住在同一个地址?

解决方案

Kavya写道:


offsetof(T,m)(size_t)&(((T *)0) - > m)


为什么我们总是从这个宏的0开始访问

结构或联合的偏移量。标准保证结构和联合

是否位于地址0?



否。宏涉及未定义的行为。我假设您在

中找到了这个宏标准库实现的代码:请注意,编译器的标准库的实现者

允许使用具有<的代码br />
未定义的行为,只要编译器保证正确的行为

(即使标准不要求它)。或者,可以使用编译器魔法来实现offset $



如果是,那么如果我有两个或更多结构怎么办?他们怎么能住在

同一地址?



他们不是;并且编译器会抱怨,如果它不是为了演员

告诉它闭嘴。

最好


启-Uwe Bux


Kavya写道:


offsetof(T,m)(size_t)&(( (T *)0) - > m)


为什么我们总是从这个宏的0开始来访问

结构或联合的偏移量。标准保证结构和联合

是否位于地址0?如果是,那么如果我有两个或更多

结构怎么办?他们怎么能住在同一个地址?



这只是一个非常黑客。请记住,结构或联合没有地址,因为它们只定义了这种类型的内存布局和

实际对象的行为。在上面的hack偏移中,我们将一个指针

加到一个类型为T的实例x上并计算&(x-> m)之间的差值

和& x 。当然,我们使用的指针无效,这意味着我们不能在不引发未定义行为的情况下取消引用它。所以我们可以选择

任何指针值:

#define offsetof(T,m)(size_t)(&(((T *)0x12345678) - > m) - &((T *)

0x12345678)))

也可以,但不清楚为什么我们使用这个特殊的

指针0x12345678。所以我们坚持使用NULL指针,这恰好与某些平台上的虚拟地址0x00000000重合(这个偏移的
版本不是很便携,BTW)。这样我们就不需要

来减去第二项&((T *)0),因为无论如何这将评估为

0x00000000(所有指针值)在这个例子中只对

32位机器有效。


偏离平台的更多独立版本将是:

#define offsetof(T,m)(size_t)(&(((T *)0) - > m) - &((T *)0))

问候,

Stuart


@ALL:这不应该在FAQ中吗?


< blockquote> Stuart Redmann写道:


>

偏离平台的更多独立版本将是:

#define offsetof(T,m)(size_t)(&(((T *)0) - > m) - &((T *)0))



不要尝试编写与平台无关的标准库版本

hacks。偏移的主要原因之一是在标准库中是

,它不能写入便携式。


请注意,这个版本只是不行。除非m

和T是相关类型,否则它是不正确的,即便如此,它也会得到错误的答案。你需要将两个指针都转换为某些char *的指针。当你完成这件事的时候,它几乎是不可读的。


-


- Pete


标准C ++库扩展:教程和
参考的作者。有关本书的更多信息,请参阅
www.petebecker.com/tr1book


offsetof(T,m) (size_t)&(((T*)0)->m)

Why do we always start from 0 in this macro to access the offset of
structure or union. Does standard guarantees that structure and union
reside at address 0? If yes, then what if I have two or more
structures. How can they reside at same address?.

解决方案

Kavya wrote:

offsetof(T,m) (size_t)&(((T*)0)->m)

Why do we always start from 0 in this macro to access the offset of
structure or union. Does standard guarantees that structure and union
reside at address 0?

No. The macro involves undefined behavior. I presume you found this macro in
the code of your standard library implementation: note that the implementor
of the standard library for your compiler is allowed to use code that has
undefined behavior as long as the compiler guarantees the right behavior
(even though the standard does not require it). Alternatively, offsetof
could be implemented using compiler magic.

If yes, then what if I have two or more structures. How can they reside at
same address?.

They don''t; and the compiler would complain if it wasn''t for the casts
telling it to shut up.
Best

Kai-Uwe Bux


Kavya wrote:

offsetof(T,m) (size_t)&(((T*)0)->m)

Why do we always start from 0 in this macro to access the offset of
structure or union. Does standard guarantees that structure and union
reside at address 0? If yes, then what if I have two or more
structures. How can they reside at same address?.

This is only a pretty hack. Keep in mind that structures or unions have
no address as they only define the memory layout and the behaviour of
real objects of this type. In this offsetof hack above we take a pointer
to one instance x of type T and compute the difference between &(x->m)
and &x. Of course, the pointer we use is not valid, that means we cannot
dereference it without provoking undefined behaviour. So we could choose
just any pointer value:
#define offsetof(T,m) (size_t)(&(((T*) 0x12345678)->m) - &((T*)
0x12345678)))
would work as well, but it is not clear why we used this particular
pointer 0x12345678. So we stick to the NULL pointer, which happens to
coincide with the virtual address 0x00000000 on some platforms (this
version of offsetof is not very portable, BTW). This way we don''t need
to subtract the second term &((T*) 0), as this would evaluate to
0x00000000 anyway (all pointer values in this example are only valid for
32 bit machines).

A more platform-independent version of offsetof would be:
#define offsetof(T,m) (size_t)(&(((T*)0)->m) - &((T*)0))

Regards,
Stuart

@ALL: Shouldn''t this be in the FAQ?


Stuart Redmann wrote:

>
A more platform-independent version of offsetof would be:
#define offsetof(T,m) (size_t)(&(((T*)0)->m) - &((T*)0))

Don''t try and write platform-independent versions of standard library
hacks. One of the main reasons offsetof is in the standard library is
that it can''t be written portably.

Note, too, that this version just doesn''t work. It''s ill-formed unless m
and T are related types, and even then, it gets the wrong answer. You
need to cast both pointers to some flavor of char*. By the time you''ve
done that, it''ll be pretty much unreadable.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.


这篇关于offsetof()宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆