Search code examples
cc99unions

Accessing inactive union members


If I have the following code:

#include <stdint.h>
union data_t {
  int8_t sbyte;
  uint8_t ubyte;
  int16_t sint;
  uint16_t uint;
  int32_t slong;
  uint32_t ulong;
  int64_t sint64;
  uint64_t uint64;
  float qsingle;
  double qdouble;
  long double qfloat;
};
union data_t *data;
data = malloc(sizeof(union data_t));
data.uint = 2534;

Here, I have assigned the uint16_t type as 42, an I safely access a data type smaller than the one I have assigned to (such as uint8_t), and have it safely typecast (to 230)? This answer (Accessing inactive union member and undefined behavior?) seems to say that it is allowed in C11, but I'm unsure as to whether or not this is legal in C99.


Solution

  • It's probably compiler specific due to how it arranges the underlying data in the union. Essentially accessing by an 'inactive' member is just interpreting the data differently. Interpreting a large int as a smaller one should work.

    [FF|01] < a uint16
    

    A uint8 just reads the first byte of that data:

    [FF|01]
         ^ read    
    ^ ignored
    

    Interpreting a float as an int or viceversa is unlikely to work, since the underlying bits won't make sense:

    [0x1|0xF|0x7FFFFF]
               ^ 23-bit mantissa
          ^ 8-bit exponenent
      ^ sign bit