0

I've been told that a class' memory always has the same structure:

So if I have the pointer to a member of a class, can I somehow calculate the pointer to that class?

class num
{
public:
    num() {}
    int a;
    int b;
};

int* ptr; // we have the pointer to num.b
num* number; // we want the pointer to num

Would it be possible to get "number" with only "ptr"? Something like this:

num temp;
int diff = (void*)&temp - (void*)&temp.b;

num target;
int* ptr = &target.b;
num* number = (num*)((void*)ptr + diff);
ZeroZ30o
  • 375
  • 2
  • 18
  • 1
    You might be able to use [`offset`](https://en.cppreference.com/w/cpp/types/offsetof) if your type is a [standard layout type](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout). But there's no way to know if a given pointer points to a data member of a given type. It might point to a member of a different class type, a local variable or something else. – François Andrieux Oct 11 '18 at 17:16
  • 1
    `int* ptr = target.b;` should be `int* ptr = &target.b;` also may i ask what your use case for this is? – Borgleader Oct 11 '18 at 17:16
  • @Frank But it appearing to work is not sufficient evidence that it's correct/reliable/sane. – Lightness Races in Orbit Oct 11 '18 at 17:21
  • @LightnessRacesinOrbit I don't know what you are referring to. – François Andrieux Oct 11 '18 at 17:21
  • It is undefined behaviour to do that. Even if all your address calculations are correct, it's still illegal. – n. m. could be an AI Oct 11 '18 at 17:24
  • @FrançoisAndrieux alright, so it would work with offset under very specific class conditions, but otherwise this -or an alternative way to do it- isn't possible, yes? – ZeroZ30o Oct 11 '18 at 17:27
  • @Borgleader ty, corrected -my use case is having a member class purposefully created to notify other parts of the code of the new address of the class that contains it. Specifically, the member class would be an "observer" that subscribes and notifies an "observed" object somewhere else in the program of every memory movement the holding class does. – ZeroZ30o Oct 11 '18 at 17:30
  • @ZeroZ30o I think it works for some cases, but I'm having a hard time proving it since the c++ standard refers to the c standard for `offset` so you have to be extra careful interpreting the standard. And there isn't much in the way of concise documentation on what `offset` can be used for. But there is no general solution to this problem. Depending on the use case you could hack a solution, such as keeping a map that maps all `b`s to their owner. But I would bet this is a design issue and this question is trying to circumvent fixing it. – François Andrieux Oct 11 '18 at 17:30
  • @FrançoisAndrieux well, what this is trying to accomplish is what I mentioned in the last message to someone else. – ZeroZ30o Oct 11 '18 at 17:32
  • @ZeroZ30o Could that notifier class not just take a pointer to it's owning instance instead, and pass that around? – François Andrieux Oct 11 '18 at 17:33
  • Note: difference btw 2 pointers is a number, not another pointer. – Slava Oct 11 '18 at 17:35
  • @FrançoisAndrieux I don't understand- the issue is that the notified (observer) moves around in memory, and so the notifier (observed) will then hold an invalid pointer. It's the observer's job to update it. – ZeroZ30o Oct 11 '18 at 17:37
  • @ZeroZ30o If something "moves around in memory" it's actually creating new instances or assigning values, probably with move semantics. You can use constructors and assignment operators to track it. The owning instance will have to create new observer members, so it will know it's own address which it can pass to the observer. I'm assuming the scheme you are aiming for is to signal `this` from your observer and to then try to deduce the address of the owning object. If not, I may have misunderstood. You'll have to share a more complete example. – François Andrieux Oct 11 '18 at 17:39
  • @FrançoisAndrieux no, you did understand properly, and I do realize that I could add move semantics to every class observing something. However I thought it would save a lot of time to make pairing classes that save me the time of creating that same behavior every time. AKA just put "observer" in a class that moves in memory and its address would be updated automatically in the observed object. – ZeroZ30o Oct 11 '18 at 17:41
  • @ZeroZ30o To be clear, objects never move in memory. Only an object's value can move. Once an object is created, it's address is fixed for it's entire lifetime and cannot change under any circumstance. – François Andrieux Oct 11 '18 at 18:11
  • @FrançoisAndrieux yes I do understand, I just want the move constructor/copy assignment operator of the observer class to send a notification to the observed object, containing the new address of the owner object. – ZeroZ30o Oct 11 '18 at 18:20

1 Answers1

4

In theory, if everything were just a bunch of bytes, then yes.

But no.

C++ is an abstraction. A really complex one. Your compiler is also really complex. It likes to make assumptions — using the guarantees and constraints set out by the standard — in order to produce the best code possible from your abstract description of a program.

Ambling around with pointer arithmetic between different objects is, I'm afraid, one of those things that is not permitted. Expect weirdness as a result if you try.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055