访问非活动的工会成员

时间:2013-06-07 13:06:02

标签: c c99 unions

如果我有以下代码:

#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;

在这里,我已经将uint16_t类型指定为42,我安全地访问小于我指定的数据类型(例如uint8_t),并安全地进行类型转换(到230)?这个答案(Accessing inactive union member and undefined behavior?)似乎说它在C11中被允许,但我不确定这是否在C99中是合法的。

2 个答案:

答案 0 :(得分:2)

这个问题的答案在C99 C11中没有明确定义。在这两个标准中,§6.2.6.1p7说:

  

当一个值存储在union类型的对象的成员中时,   对象表示的字节与该对应的字节不对应   成员,但确实对应其他成员采取未指定的值。

在设置不同的成员后,我肯定会发现访问qsingleqdoubleqfloat成员时遇到问题。这些成员可能具有导致SIGFPE等信号的表示,并且从这样的信号处理程序返回是未定义的行为。

答案 1 :(得分:1)

由于它如何在联合中排列基础数据,因此可能是编译器特定的。基本上由“非活动”成员访问只是以不同方式解释数据。将大型int解释为较小的 应该工作。

[FF|01] < a uint16

uint8只读取该数据的第一个字节:

[FF|01]
     ^ read    
^ ignored

float解释为int或反之亦然,因为基础位无效:

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