0

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.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Flukiluke
  • 85
  • 1
  • 1
  • 3

2 Answers2

2

The answer to this question not well defined in C99 or C11. In both standards, §6.2.6.1p7 says:

When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.

I would certainly see a problem with accessing the qsingle, qdouble and qfloat members after setting a different member. These members might have representations that cause signals such as SIGFPE to be raised, and returning from such a signal handler is undefined behaviour.

autistic
  • 1
  • 3
  • 35
  • 80
1

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
Antonio
  • 19,451
  • 13
  • 99
  • 197
Chris
  • 16,872
  • 1
  • 15
  • 16
  • Okay, thanks for that. I don't plan to cast to r from floating point numbers, just the integers. If it is compiler-specific as you say, I guess I'll just avoid it. – Flukiluke Jun 08 '13 at 03:35