3

I've been looking at some AOSP code, and I came across this (from a 5.0+ branch, under art/runtime/base/macros.h)

#define OFFSETOF_MEMBER(t, f) \
  (reinterpret_cast<const char*>(&reinterpret_cast<t*>(16)->f) - reinterpret_cast<const char*>(16)) // NOLINT

This is used in calls such as:

MemberOffset(OFFSETOF_MEMBER(Class, dex_cache ));

Where Class is a class and dex_cache is a member under that class. This returns the offset of the field and then is used as the constructor of a MemberOffset class.

My question is why on earth would you want to hardcode that "16" in there? Wouldn't it make more sense just take the address of the member and subtract the base address of the class?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Maxthecat
  • 1,250
  • 17
  • 37
  • This is "trial and error programming"... probably someone heard that using 0 instead of 16 there is bad, so they had the bright idea of putting a different number in and seeing if it worked. Maybe it works on some architectures. – M.M Mar 22 '16 at 21:37
  • Note that there *is* no address of a member or address of a base class here, because there's no *object in memory*--the first argument to the macro is a *class* name, not an *object*. So your proposed "fix" wouldn't actually be feasible. I'm assuming that part of the reason it's `16` and not `0` is that `0` would be (statically provable) `nullptr` and therefore the compile could fail. – Kyle Strand Mar 22 '16 at 21:40
  • Also, as far as I can tell, with a modern compiler, `std::declval` should make this sort of trickery unnecessary. It's [not actually implemented this way](http://stackoverflow.com/q/14657092/1858225), but I imagine it could be close. – Kyle Strand Mar 22 '16 at 21:44
  • @KyleStrand can you suggest some actual code using declval ? – M.M Mar 22 '16 at 21:48
  • @M.M My mistake; `declval` (for obvious reasons) doesn't permit ODR-use of its return value, and comparison of memory addresses counts. – Kyle Strand Mar 22 '16 at 22:14

1 Answers1

2

You can't subtract base address of class. You could do that for base address of object, but you do not have any. So, the macro converts address 16 into that base address.

Why not 0? Lint would complain. Why not 1? Structure alignment problems.

DigiDream
  • 36
  • 2
  • Good point. I missed that they weren't actually using an object and were just trying to get a decltype. – Maxthecat Mar 22 '16 at 21:56