Is casting GLib / GTK pointers undefined behavior?

Viewed 123

Since C doesn't support inheritance, GLib / GTK emulates it by placing base class object as the first member of derived class object. I suppose it is something like this:

struct Parent
{
    //...
};

struct Child
{
    Parent base;
    //...
}

Then we can cast child struct pointer to parent struct pointer:

Child  *p_child  = make_child();
Parent *p_parent = (Parent*)p_child;

In C++ it can be done using reinterpret_cast:

Parent *p_parent = reinterpret_cast<Parent*>(p_child);

But as far as I know it is UB because Child and Parent are unrelated classes.

Is it undefined behavior in C++? Is it undefined behavior in C?

In GLib / GTK there are converting macros:

GtkWindow *p_window = ...;
GtkWidget *p_widget = GTK_WIDGET(p_window);

I don't know what they actually do. Do they use some special operations to make casting defined behavior?

1 Answers

Notice: This answer is only addressing the C part of the question

Is it undefined behavior in C?

No, it's legal to convert a pointer to a struct to a pointer of the same type as the first element of the struct.

Your code isn't valid C because of a missing struct keyword but the principle is fine. Code like this is valid in C:

struct Parent
{
    int id;
}

struct Child
{
    struct Parent parent;
    int n;
}

struct Child * c = malloc(sizeof *c);
struct Parent * p = (struct Parent*)c;  // Valid because the first member of 
                                        // struct Child is a struct Parent
p->id = 42;
printf("%d\n", c->parent.id;  // Will print 42
Related