0

I have the following data design:

struct Info {
    int i;
};

struct Data {
    long data;
}


struct C {
    Info I;
    Data d;
};

int main() {
    C c;
    Data* d=&(c.d);
    C* getOuterC(d);
}

Now I have a pointer to Data (Data*) that I know is inside a C struct. I would like to have a function C* getOuterC(Data*) function returning a C pointer (C*) to the outer C structure containing Data. Any idea?

Javaddict
  • 483
  • 1
  • 4
  • 15
  • Proper way? Have a pointer to the outer inside the data struct. Crazy, dangerous and relying on implementation specifics? Calculate the pointer value as `d - sizeof(Info)`. – adnan_e Nov 09 '20 at 21:15
  • 1
    https://stackoverflow.com/questions/142016/c-c-structure-offset -- note that in C++ the support for [`offsetof`](https://en.cppreference.com/w/cpp/types/offsetof) is implementation dependent. If you think you need this _and_ you have to ask about it on Stack Overflow, I assert that you don't need it and there's a problem with your design. – paddy Nov 09 '20 at 21:17
  • I don't think that's possible without using some questionable methods, but you could change `Data` to have a pointer to its parent `C` –  Nov 09 '20 at 21:17
  • 1
    By the way, the behavior of the accepted answer in that duplicate is undefined (pointer arithmetic is only valid within arrays). – Bathsheba Nov 09 '20 at 21:21
  • @Bathsheba There is a proposal in flight (last I checked) to make it valid within objects, though - i.e. to take that one bit of wording that indicates an object can be treated as 'an array of `unsigned char`' (or, now ,`std::byte`) and actually make it usable by not contradicting it elsewhere in the Standard. Or at least, that's what I recall of it! – underscore_d Nov 09 '20 at 21:25
  • @underscore_d: Yes there is all that standard layout malarkey. – Bathsheba Nov 09 '20 at 21:27

1 Answers1

1

There is no portable way of doing what you want, unless you change the base classes in some way.

One solution is to make Info and Data polymorphic types: do that by introducing a virtual destructor in both:

struct Info {
    virtual ~Info() = default;
    int i;
};

and similar for Data.

Then you refactor C as follows:

struct C : Info, Data
{
};

Then if you have a pointer (or reference) to either, you can reach the other, and the base class C with a dynamic_cast. That will form the basis for the function that you want to write.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Sure, that looks right now. At least... one _can_ do that, but I would push back on it if I saw it in real life, as inheritance is rarely a solution, and this smells like probably an XY problem. – underscore_d Nov 09 '20 at 21:21