同时访问c联盟的不同成员

时间:2017-01-18 13:44:10

标签: c struct unions xlib xorg

我遇到了一段似乎同时使用不同成员联合的代码:

XEvent ev;

if(handler[ev.type])
    (handler[ev.type])(&ev);

Handler是一组函数。这是XEvent的定义:

typedef union _XEvent{
    int type;/*must not be changed*/
    XAnyEvent xany;
    XKeyEvent xkey;
    XButtonEvent xbutton;
............
} Xevent;

XEvent的所有struct成员都有一个int作为第一个成员。被调用的函数使用XEvent的适当成员结构。

void
kpress(XEvent *ev) {
    XKeyEvent *e = &ev->xkey;

问题是XKeyEvent似乎也使用其第一个int成员的值来确定该事件是按键还是键释放。

typedef struct {
    int type; /* KeyPress or KeyRelease */
    unsigned long serial;   /* # of last request processed by server */
    .............
} XKeyEvent;

我在这里缺少什么?

注意:以上代码属于简单终端,终端仿真器。所有提到的数据结构都属于Xlib。

2 个答案:

答案 0 :(得分:2)

我花了一段时间才知道你认为你的问题在哪里 - 因为实际上没有...

您似乎假设事件类型整数与结合中有效的结构之间必须存在1:1的关系。不,没有。

Xlib的作用是:它将为KeyPress和KeyRelease事件设置相同的XKeyEvent结构(它们使用相同的数据成员,因此可用于两种事件情况)。

X11窗口系统将XEvents作为不透明结构(或在OOP术语"基类")中发送,接收器可以转换为原始结构(或在OOP术语"派生类")根据事件类型。重叠的int成员"类型"用作类型选择器。

这样做是为了能够"路由"通用代码中的事件到正确的位置而不必处理每个事件类型。只有感兴趣的一方(实际的接收方)才会将内部联盟转换为正确的类型,并且#34;提取"它感兴趣的数据成员。

答案 1 :(得分:1)

C99(以前的C标准)和现在的C11,即使不是最后一个成员,也允许阅读工会会员。

他们声明(并且我会解释)最后写成员的价值被重新解释为正在阅读的成员的价值(如果他们的规模不同,则表现为"人们会期望&# 34)。该值可能是陷阱值,但允许简单的读取操作,而不是未定义的行为。

现在,该标准还指定如果联合包含多个共享相同初始序列的成员结构,则可以通过任何联合成员检查公共序列。

type中的{p> XEvent不是一个结构,但标准中又说了两件事:

  1. 适当转换的结构指针指向第一个成员。
  2. 适当转换的联合指针指向任何联盟成员。
  3. 因此,每个结构中的每个type必须与type中的XEvent位于同一内存位置。因此,无论您正在阅读ev.type还是ev.xkey.type,它都将是相同的int。

    所以你的代码中发生了什么:

    1. 联合用于类型擦除。只有type字段用于确定正确的处理程序。没有任何事情可以阻止在handler中在type的几个值上注册相同的功能。

    2. 处理程序知道要查看的联合成员,因此它访问xkey。然后它根据type

    3. 的值起作用