2015-08-31 2 views
3

Насколько я понимаю союза в C могу содержать только 1 значение в то время, и я не понимаю, как этот код в C имеет смысл, поскольку event.window не может быть заполнен в то же время, что и event.type?C союз - пожалуйста, объясните

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

+0

Тег C++, вероятно, неверен. –

ответ

4

Каждый агрегат (struct наверное) член SDL_CommonEvent common;, SDL_WindowEvent window;, SDL_KeyboardEvent key; и т.д. ... из union SDL_Event начинается с некоторого Uint32 поля, давая type и это общее поле type имеет одинаковый адрес и размер в каждом члене профсоюза.

Таким образом, хотя союз действительно содержит только одно поле в памяти (другими словами, все члены объединения имеют один и тот же адрес), каждый из которых начинается с type и имеет смысл event.type; он извлекает это type.

Такая идиома является обычным способом в C для реализации tagged unions.

+0

Интересно, спасибо! –

4

Каждый член союза SDL_Event начинается с тех же двух элементов, Uint32 type и Uint32 timestamp. В стандарте C конкретно говорится, что если объединение в настоящее время содержит значение одного типа структуры, но читается как другой тип структуры, чьи первые члены соответствуют другому типу структуры, вполне нормально читать соответствующие члены.

2

Все остальные SDL_X типы все начинаются с типа 32 бит. Фактически, все они, кажется, включают поля в SDL_CommonEvent в начале. Это должно облегчить доступ к общим элементам ко всем подструктурам. Затем, по event.common.x, вы можете получить доступ ко всем общим элементам без необходимости различать точный тип события.

Смежные вопросы