From http://blog.chinaunix.net/u2/62910/showart_492571.html
Assume that a structure type named mystruct is defined in the ansi c program, and a field named myfield exists. How can we get its offset in the struct?
Typedef struct mystruct_tag
{
// Some fields
...
Long myfield;
// Other fields
...
} Mystruct;
The easiest way to think of is similar to the following code:
Size_t getoffset ()
{
Mystruct S;
Return (size_t) (char *) (& S. myfield)-(char *) (& S ));
}
This code can indeed complete the task, but in order to get the offset value, the function has to define a mystruct struct instance. Is this necessary? When will the memory layout of the struct be determined? Yes, it is determined by the compiler during the compilation period. Once determined, it will not change, and the field offset dependent on the Structure memory layout will be determined and will not change. Since the compiler understands the inside story at the compilation stage, there is no reason to require it to provide this information to the program during the compilation phase. What should we do? See the following code:
# Define my_offset (size_t) & (mystruct *) 0)-> myfield)
The my_offset macro defined above is the offset of the desired myfield. In this way, how can the structure pointer after forced conversion be used to access the struct field? In fact, this expression is neither intended nor intended to access the myfield field. Ansi c standard allows any constant with a value of 0 to be forcibly converted to any type of pointer, and the conversion result is a null pointer, so (mystruct *) 0) the result is a null pointer of the mystruct * type. If the use of this NULL pointer to access mystruct members is of course illegal, but the intention of & (mystruct *) 0-> myfield) is not to access the content of the myfield field, instead, it only calculates the address of the myfield field when the first address of the struct instance is (mystruct *) 0. A smart compiler does not generate code to access myfield, but simply calculates this (constant) address during compilation based on the memory layout of mystruct and the first address of the struct instance, this completely avoids the problem of accessing the memory through the NULL pointer. Because the value of the first address is 0, the value of this address is the offset between the field and the base address of the struct.
The above practice avoids the need to instantiate a mystruct object, and evaluate the value during the compilation period, without the runtime burden. In fact, This method uses the information of the entire program obtained by the compiler to calculate some values during the compilation period is similar to the popular (static) metaprogramming Technology in C ++ programming, however, C ++ programmers can use the template technology to perform very complex computation during the compilation period, while ansi c, which lacks template support, is much weaker in this respect.
It may be very common to calculate the struct field offset. ansi c is in the standard header file stddef. h defines a macro in the form of offsetof (S, m) to calculate the offset of a field in any structure type, in addition, the vast majority of C development systems adopt the above methods, such:
// Vc7.1
# Ifdef _ win64
# Define offsetof (S, m) (size_t) (ptrdiff_t) & (S *) 0)-> m ))
# Else
# Define offsetof (S, m) (size_t) & (S *) 0)-> m)
# Endif
// Lcc-win32, last updated: Monday, 13-dec-2004 04:05:23 est
# Define offsetof (S, m) (INT) & (S *) 0)-> m)
// Borland C ++ 5.5.1 for Win32
# Define offsetof (s_name, m_name) (_ size_t) & (s_name _ far *) 0)-> m_name)
// Mingw 3.1.0 (GCC 3.2.3)
# Ifndef _ cplusplus
# Define offsetof (type, member) (size_t) & (type *) 0)-> Member)
# Else/* C ++ */
/* The reference cast is necessary to things an operator & that might
Be applicable to Member's type. See Dr 273 for details .*/
# Define offsetof (type, member) (reinterpret_cast <size_t>/
(& Reinterpret_cast <char &> (static_cast <type *> (0)-> member )))
# Endif/* C ++ */
It can be seen that this concise and effective method has been accepted by C programmers as an idiom (idiom.