0

In the code, child is casted to type Parent, and passed to parentMove. child does not have members x and y. How does parentMove access child.parent.x and child.parent.y? How does type casting work here? Thx

#include <stdio.h>

typedef struct{
    int x, y;
    int (*move)();
}Parent;

typedef struct {
    Parent parent;
    int h, w;
}Child;

int parentMove(Parent* parent, int y, int x){
    parent->y+=y;
    parent->x+=x;
    printf("%d %d", parent->y, parent->x);
    return 1;
}

int main(void) {
    Parent parent = {.x = 2, .y = 1, .move = &parentMove};
    Child child = {.parent = parent, .h = 3, .w = 4};
    ((Parent*)(&child))->move((Parent*)&child, 10, 10);
    return 0;
}
Austin
  • 41
  • 1
  • 4
  • 2
    See [Is pointer to struct a pointer to its first member?](https://stackoverflow.com/questions/53578631/is-pointer-to-struct-a-pointer-to-its-first-member). `&child == &child.parent` and the latter is a `Parent *` which is why the cast works. – dxiv Nov 16 '20 at 08:28
  • 1
    `int (*move)();` should be `int (*move)(Parent* parent, int y, int x);`, is it omitted intentionally? – csavvy Nov 16 '20 at 08:42
  • @csavvy I know it works so I just omitted it intentionally. Well it's a bad habit though – Austin Nov 16 '20 at 08:45
  • 2
    @Austin AFIK that's UB. So it does not work. It just behaves like it does. – klutt Nov 16 '20 at 08:55

2 Answers2

1

How does parentMove access child.parent.x and child.parent.y?

It doesn't know about the child part. It doesn't matter if a Parent object is declared as a stand-alone object or as a member of Child, same thing applies in either case.

How does type casting work here?

Poorly... you have implemented inheritance incorrectly if you have to cast to the base class from the caller side. It would seem that Child should have implemented its own move that takes a Child* as parameter, if only to make it a wrapper to the parent.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

How does type casting work here?How does parentMove access child.parent.x and child.parent.y?

In child structure, the first member is the parent structure, so internally memory representation of child structure is --

{
    {
        int x;         [ .. 4bytes .. ]
        int y;         [ .. 4bytes .. ]
        int *move();   [ .. 4bytes .. ]
    }
    int h;             [ .. 4bytes .. ]
    int w;             [ .. 4bytes .. ]
}

When you access parent.x , It is nothing but accessing first 4 bytes from starting address (i.e. &parent ). Similarly accessing parent.y means accessing 4 bytes after 4 bytes offset from starting address.

So when you pass address of child structure as a pointer to parent structure, the child-address actually points to a valid parent structure member inside, in the sense accessing first 4 bytes from the child-address is actually parent.x similarly other members of the contained parent structure are properly be accessed.

gobinda
  • 124
  • 3