0

如果我有以下代码:

#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中是否合法。

4

2 回答 2

2

这个问题的答案在 C99C11 中没有很好地定义。在这两个标准中,§6.2.6.1p7 说:

当一个值存储在联合类型对象的成员中时,对象表示中不对应于该成员但对应于其他成员的字节采用未指定的值。

在设置不同的成员后,我肯定会看到访问qsingle,qdouble和成员的问题。qfloat这些成员可能具有导致诸如SIGFPE被引发的信号的表示,并且从这样的信号处理程序返回是未定义的行为。

于 2013-06-07T13:20:43.980 回答
1

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

[FF|01] < a uint16

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

[FF|01]
     ^ read    
^ ignored

将 a 解释float为 aint或反之亦然不太可能起作用,因为基础位没有意义:

[0x1|0xF|0x7FFFFF]
           ^ 23-bit mantissa
      ^ 8-bit exponenent
  ^ sign bit
于 2013-06-07T13:11:21.887 回答