C联合体 - 请解释

6
据我所知,C语言中的联合(union)一次只能保存一个值,我并不明白这段C代码是如何正确运行的,因为event.window和event.type不能同时存在。
while(SDL_PollEvent(&event)) {
switch(event.type)
{
case SDL_WINDOWEVENT:
    switch(event.window.event)

该事件的定义如下:
typedef union SDL_Event
{
    Uint32 type;                    /**< Event type, shared with all events */
    SDL_CommonEvent common;         /**< Common event data */
    SDL_WindowEvent window;         /**< Window event data */
    SDL_KeyboardEvent key;          /**< Keyboard event data */
    SDL_TextEditingEvent edit;      /**< Text editing event data */
    SDL_TextInputEvent text;        /**< Text input event data */
    SDL_MouseMotionEvent motion;    /**< Mouse motion event data */
    SDL_MouseButtonEvent button;    /**< Mouse button event data */
    SDL_MouseWheelEvent wheel;      /**< Mouse wheel event data */
    SDL_JoyAxisEvent jaxis;         /**< Joystick axis event data */
    SDL_JoyBallEvent jball;         /**< Joystick ball event data */
    SDL_JoyHatEvent jhat;           /**< Joystick hat event data */
    SDL_JoyButtonEvent jbutton;     /**< Joystick button event data */
    SDL_JoyDeviceEvent jdevice;     /**< Joystick device change event data */
    SDL_ControllerAxisEvent caxis;      /**< Game Controller axis event data */
    SDL_ControllerButtonEvent cbutton;  /**< Game Controller button event data */
    SDL_ControllerDeviceEvent cdevice;  /**< Game Controller device event data */
    SDL_QuitEvent quit;             /**< Quit request event data */
    SDL_UserEvent user;             /**< Custom event data */
    SDL_SysWMEvent syswm;           /**< System dependent window event data */
    SDL_TouchFingerEvent tfinger;   /**< Touch finger event data */
    SDL_MultiGestureEvent mgesture; /**< Gesture event data */
    SDL_DollarGestureEvent dgesture; /**< Gesture event data */
    SDL_DropEvent drop;             /**< Drag and drop event data */

    /* This is necessary for ABI compatibility between Visual C++ and GCC
       Visual C++ will respect the push pack pragma and use 52 bytes for
       this structure, and GCC will use the alignment of the largest datatype
       within the union, which is 8 bytes.

       So... we'll add padding to force the size to be 56 bytes for both.
    */
    Uint8 padding[56];
} SDL_Event;

2
其他联合事件以 Uint32 type; 开始。 - Jarod42
1
union 是同一二进制数据的不同“视角”集合。您可以分配联合的所有可能成员,但每个后续分配都将覆盖之前存储的值。 - i486
"C++" 标签可能是错误的。 - Basile Starynkevitch
3个回答

8
每个union SDL_Event的聚合(可能是struct)成员SDL_CommonEvent common;SDL_WindowEvent window;SDL_KeyboardEvent key;等都以一些Uint32字段开头,给出了type,而且每个联合成员的公共type字段在地址和大小上都相同。
因此,尽管联合在内存中只携带一个字段(换句话说,所有联合成员具有相同的地址),但它们中的每一个都以一个type开始,event.type有意义;它获取该type
这种惯用法是C语言中实现tagged unions的常见方式。

4

SDL_Event联合体的每个成员都以相同的两个成员Uint32 typeUint32 timestamp开头。C标准明确规定,如果一个联合体当前保存了一个结构类型的值,但按照另一种结构类型读取,且这两种结构类型的第一个成员匹配,那么读取这些匹配的成员是可以的。


2

所有其他的SDL_X类型都以32位类型开始。实际上,它们似乎都包括在开头的SDL_CommonEvent字段中。这是为了方便访问所有子结构的公共元素。然后,通过event.common.x您可以访问所有常见元素,而不必区分事件的确切类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接