Use a macro to define "FIND" to FIND the amount of data transferred from a variable in the struct structure to struc.
Example: stuct student
{
Int;
Char B [20];
Double ccc;
}
Then:
FIND (student, a); // equals 0
FIND (student, B); // equals to 4
# Define FIND (struc, e) (size_t) & (struc *) 0)-> e)
(Struc *) 0 ---------- indicates to forcibly convert constant 0 to the address pointed to by struc * pointer
& (Struc *) 0)-> e) -- returns the address of e, a member of struc * 0, because the first address of the struct is 0, so we get the offset of member e from the first address of the struct.
(Size_t) ----------- is a type of data. To facilitate transplantation between different systems, it is defined as unsigned int.
(Struc *) 0 indicates that there is a structure struc at address 0.
(Struc *) 0)-> e indicates the struc member e at the zero address.
& (Struc *) 0)-> e) indicates the address of the struc member e at the zero address
(Size_t) & (struc *) 0)-> e) convert the address of member e of struc at the zero address to an integer.
# Define OFFSETOF (type, field) (size_t) & (type *) 0)-> field ))
(Type *) 0: regards the 0 address as a pointer of the type.
(Type *) 0)-> field: the variable of the corresponding field.
& (Type *) 0)-> field: obtains the address of the variable, which is equal to the offset of the field relative to the 0 address.
(Size_t) & (type *) 0)-> field): converts the address (offset) to size_t type data.
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 (s *) 0) the result is a NULL pointer of type s. If the use of this NULL pointer to access s members is of course illegal, but the intention of & (s *) 0)-> m) is not to access s field content, it only calculates the address of the m field when the first address of the schema body instance is (s *) 0. A smart compiler does not generate code to access m at all. Instead, it only calculates the (regular) address during compilation based on the memory layout of s and the first address of the struct instance, this completely avoids the problem of accessing the memory through the NULL pointer.