Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does this C inheritance implementation contain undefined behavior?

struct parent
{
    char a;
    char b;
};

struct child
{
    struct parent parent;
    int c;
    char d;
};

struct grandchild
{
    struct child child;
    long e;
};

void print_parent_val(struct parent *p)
{
    printf("%d\n", p->a);
}

int main (int argc, char **argv)
{
    struct grandchild g;
    g.child.parent.a = 69;
    print_parent_val((struct parent *)&g);
    return 0;
}

The program compiles (no warnings) and runs fine and prints 69 as expected. I have never seen any code that implements this inheritance technique so I'm very hesitant to see this as "OK".

EDIT: What about converting the grandchild to just a child? Is the mid-generation conversion also possible?

void print_parent_val(struct child *c)
{
    printf("%c\n", c->d);
}

int main (int argc, char **argv)
{
    struct grandchild g;
    g.child.parent.a = 69;
    g.child.d = 'w';
    print_parent_val((struct child *)&g);
    return 0;
}
like image 207
Dellowar Avatar asked Jan 25 '17 17:01

Dellowar


Video Answer


1 Answers

As I can see, there's no scope of undefined behaviour here.

Quoting C11, chapter §6.7.2.1, Structure and union specifiers, (emphasis mine)

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

So, with the current snippet (and approach), you should be good to go.

like image 194
Sourav Ghosh Avatar answered Oct 29 '22 18:10

Sourav Ghosh