Reputation: 11318
Please take a look at this macro. It is used in Symbian OS SDK, which compiler is based on GCC (< 4 version of it).
#ifndef _FOFF
#if __GNUC__ < 4
#define _FOFF(c,f) (((TInt)&(((c *)0x1000)->f))-0x1000)
#else
#define _FOFF(c,f) __builtin_offsetof(c,f)
#endif
#endif
I understand that it is calculating offset to specific class/struct member. But I cannot understand how that weird statement works - what is the constant 0x1000 and why is it there? Could somebody please explain this to me?
Upvotes: 1
Views: 421
Reputation: 26439
Imo 0x1000 is just a randomly chosen number. It is not a valid pointer, and it you could probably use zero instead of it.
How it works:
Becuase f isn't being written to, there is no accessViolation/segfault.
You could probably use zero instead of 0x1000 and discard subtraction (i.e. just use "((TInt)&(((c *)0x0000)->f))"), but maybe author thought think that subtracting base pointer from pointer to member is a more "proper" way than trying to directly cast pointer into integer. Or maybe compiler provides "hidden" class members that can have negative offset (which is possible in some compilers - for example Delphi Compiler (I know it isn't c++) provided multiple hidden "fields" that were located before "self"(analogue of "this") pointer), in which case using 0x1000 instead of 0 makes sense.
Upvotes: 2
Reputation: 882631
"If there was a member of struct c
starting exactly at the (perfectly-aligned;-) address 0x1000
, then at what address would the struct's member f
be?" -- answer: the offset you're looking for, minus of course the hypothetical starting address 0x1000
for the struct... with the difference, AKA distance or offset, computed as integers, otherwise the automatic scaling in address arithmetic throws you off (whence the cast).
What parts of the expression, specifically, are giving you problems?
The inner part &(((c *)0x1000)->f)
is "the address of member f
of a hypothetical struct c
located at 0x1000
. Right in front of it is the cast (I assume TInt
is some kind of integer type, of course), then the - 0x1000
to get the offset (AKA distance or difference between the address of the specific member of interest and the start of the whole structure).
Upvotes: 1
Reputation: 41862
It is working out the relative address of 'f' as a member of a class/struct at address 0x1000, and then subtracting 0x1000 so that only the difference between the class/struct address and the member function address is returned. I imagine a non-zero value (i.e. the 0x1000) is used to avoid null pointer detection.
Upvotes: 1