the codes in linux-2.6.16/include/linux/stddef.h is:
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
How to understand "((size_t) &((TYPE *)0)->MEMBER)"?
Thank you
The sequence of operations can be illustrated in the following way:
1. 0
2. ((TYPE *)0)
3. ( ((TYPE *)0)->MEMBER )
4. &( ((TYPE *)0)->MEMBER )
5. ( (size_t) &( ((TYPE *)0)->MEMBER )
0
.0
is cast to a pointer to struct TYPE
. IOW, we are making the compiler believe that there is such a struct
at the beginning of the program's data segment (which is generally dangerous, but I'll mention later why not in this particular case).MEMBER
within this struct
is referenced.&
),size_t
.As the address for the "start" of the struct was specified as 0
, the address of MEMBER
(when converted to a number) is its offset within the struct.
The reason why this particular code is innocuous is that no memory position is ever written, not even accessed. Everything involves just pointers to those positions (but not their contents) and numbers. All of them held in machine registers or the usual local stack.
The following expression:
( (size_t) &( ((TYPE *)3264)->MEMBER ) - 3264 )
would also work. 3264 stands for any number of your choosing. Added a parentheses set to make it more legible.
This is a hack that lets you emulate the functionality of offsetof
when there is no support by the compiler: it exploits the fact that the address of the MEMBER
equals its offset when the base address is set to zero.
Consider this example:
struct Test {
char text[32];
int count;
}
If struct Test
is allocated at the address 0xC000
, then the address of text
would be 0xC000
, and the address of count
would be 0xC020
. However, if the base address is zero (which is not allowed by the standard), then the address of text
would be zero, and the address of the count would be 0x20
. Casting these addresses to size_t
gives you the offset of the corresponding members.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With