user245019
user245019

Reputation:

Can I pass this through a function?

I'm wrapping a scripting library and this macro exists.

#define asOFFSET(s,m) ((size_t)(&reinterpret_cast<s*>(100000)->m)-100000)

what type is m? It has the example:

struct MyStruct
{
  int a;
};

asOFFSET(MyStruct,a)

I want to put this into a function.

Upvotes: 0

Views: 83

Answers (3)

Fox
Fox

Reputation: 2138

The macro is (most likely) used by the scripting library to find out the internal layout of a class's members without making assumptions about its type, architecture or inheritance model. (A simple example is discussed here).

For most C++ programs, this information (memory layout) should ideally not be needed at all. But in the off chance that you do need it (e.g. if you're writing an analyser / debugger), you would be better off retaining this macro as-is (or preferably replacing its usage in your code with offsetof as Michael Anderson points out.) There are compiler-specific implementations which are

  1. more efficient
  2. less likely to be reported as performing an invalid operation (e.g. dereferencing an invalid memory address when using tools like Valgrind).

With these equivalent options, a hand-spun alternative or wrapper should ideally not be needed.

Upvotes: 1

Karl Knechtel
Karl Knechtel

Reputation: 61498

The purpose of the macro is to determine, given any name of a struct and any name of a member of that struct, the distance in memory from the beginning of an arbitrary instance of the struct, and the location of that member in the same instance.

m does not have a "type", and neither does s. The entire concept of "type" goes out the window when you use macros. This stuff simply is not C++; it's basically a completely separate language that's used to edit C++ code in-place. When the preprocessor runs, asOFFSET(MyStruct, a) will be literally replaced with the text ((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000) before the compiler even begins its work.

((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000) is intended to evaluate to 0, because the a member of MyStruct instances appears at the beginning of each instance. I'm not actually 100% sure that this is legal behaviour per the specification, but the intent is as follows:

  • Pretend that there is an instance of MyStruct at the memory location 100000, by treating the number 100000 as if it were a pointer to a MyStruct.

  • Get the address in memory of the a member of this fake struct, and subtract 100000 again. That gives us the distance from the beginning of the fake struct to the specified member of that fake struct.

  • Cast that numeric value back to size_t (the numeric type used for measuring memory allocations, an unsigned integer type).

Upvotes: 0

Michael Anderson
Michael Anderson

Reputation: 73480

This is an implementation of the offsetof macro. m is any member of s. It doesn't have a corresponding C or C++ type - but is closely related to the concept of pointer to member.

Upvotes: 1

Related Questions