Unions and sharing data fields(C++)

Viewed 62

In the API documentation of SDL for the Union event it says that the the field type is shared among all the event(objects) in the union,how is this possible?

also for example this is perfectly legal

while(SDL_PollEvent(&event)){

  if(event.type == SDL_KEYDOWN){


   cout << "key down" << endl;
  }

and this is also works which logically makes more sense to me ,but I'm not sure how the first is even legal

    while(SDL_PollEvent(&event)){

   if(event.key.type == SDL_KEYDOWN){


       cout << "key down" << endl;
   }
2 Answers

A union has the potential to represent one out of multiple possible types/structures.

union {
  int i;
  float f;
  char c;
};

In the example above, the memory which holds the union can represent an int or a float or a char. But it can only be one of those things; they are mututally exclusive. The union overlaps the underlying bytes used by each member in order to save space, and assumes you will know how to correctly interpret it.

(Side note: to accommodate this, the 'size' of the union - the cloud of bytes in which the union is stored - must be large enough to hold the largest possible type defined in the union. In this case, int or float could each be 4 bytes, so the union will be at least 4 bytes.)

One neat side-effect of this overlapping memory 'trick'; if a union describes multiple struct members, then they can share common fields.

Example:

union {
  struct {
    int type;
    int i;
  } OPTION_INT;

  struct {
    int type;
    float f;
  } OPTION_FLOAT;

  struct {
    int type;
    char c;
  } OPTION_CHAR;
};

Okay, neat; the union could represent any one of three possible structs. Notice, though; they all contain the exact same first member - type. Because of the way the memory is 'overlapped', the OPTION_INT type member shares the same memory as the OPTION_FLOAT and OPTION_CHAR type members. Thus, no matter which option is correct, the type member should always exist. This is possible because they all define the type field as the very first member.

Unions -- gotta love'em :) There's no real equivalent in Java, so many Java developers find them peculiar. A union is conceptually a little like an abstract class -- a single union can have different kinds of data packed into it. The data types often have a sort of parent-child inheritance relationship -- they do in the case -- but they aren't required to. It's not unusual, for example, for see a union that consist of an integer and double -- in such a case this isn't a data structure that contains an integer and a double, but one that contains either an integer or a double, in some specific chunk of memory. The type which is actually in use has to be determined at run-time.

In this case, the SDL_Event union models a number of different kinds of event. The first field, type indicates how the rest of the data should be interpreted. If the type is SDL_KEYDOWN, then the union should be interpreted as a structure of type SDL_KeyboardEvent. The first field of SDL_KeyboardEvent is also type -- which makes some sense, since it's packed into the same space as the "base" SDL_Event. You can think of type (a little) like an attribute of the "base" SDL_Event, that can be (sort of) inherited by the specific sub-types. I'm being a bit waffly here, because the analogy is not really all that strong.

In any case, the compiler will ensure that SDL_Event is large enough to store any of the different structures it is defined to contain. Apart from type the specific structures SDL_DropEvent, SDL_KeyboardEvent, etc, don't have a lot in common, as can be seen by looking at their definitions.

In Java AWT, event classes perform almost exactly the same role as the SDL_Event union does in SDL with C.

Related