【问题标题】:Is casting GLib / GTK pointers undefined behavior?强制转换 GLib / GTK 指针是未定义的行为吗?
【发布时间】:2021-06-28 11:58:37
【问题描述】:

由于C不支持继承,GLib / GTK通过将基类对象作为派生类对象的第一个成员来模拟它.我想是这样的:

struct Parent
{
    //...
};

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

然后我们可以将子结构指针转换为父结构指针:

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

在 C++ 中可以使用 reinterpret_cast:

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

但据我所知,它是 UB,因为 Child 和 Parent 是不相关的类。

它是 C++ 中未定义的行为吗?它是 C 中未定义的行为吗?

GLib/GTK中有转换宏:

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

我不知道他们实际上在做什么。他们是否使用一些特殊的操作来进行强制转换定义的行为?

【问题讨论】:

  • 我不知道他们到底在做什么。这很容易回答:#define GTK_WIDGET 但不幸的是故事还没有结束……
  • ...在这里结束:#define _G_TYPE_CIC。似乎有一个安全(检查)版本和一个非安全版本,但最终都只是 C-cast 指针类型。

标签: c++ c gtk glib


【解决方案1】:

注意:此答案仅针对问题的 C 部分

它是 C 中未定义的行为吗?

不,将指向结构的指针转换为与结构的第一个元素相同类型的指针是合法的。

由于缺少 struct 关键字,您的代码不是有效的 C,但原理很好。这样的代码在 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

【讨论】:

猜你喜欢
  • 2019-05-24
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 2019-08-21
相关资源
最近更新 更多