开发者

Member offset macro - need details

开发者 https://www.devze.com 2023-01-04 18:33 出处:网络
Please take a look at this macro. It is used in Symbian OS SDK, which compiler is based on GCC (< 4 version of it).

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)          开发者_StackOverflow社区(((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?


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:

  1. Casts 0x1000 into class pointer (pointer of type c). - (c*)0x1000
  2. Takes pointer to "f" member of class c - &(((c *)0x1000)->f)
  3. Casts it into TInt. ((TInt)&(((c *)0x1000)->f))
  4. Substracts integer value of pointer to base (0x1000 in this case) from integer value of pointer to c's member: (((TInt)&(((c *)0x1000)->f))-0x1000)

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.


"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).


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号