【问题标题】:Accessing inactive union members访问非活动工会成员
【发布时间】:2013-06-07 13:06:02
【问题描述】:

如果我有以下代码:

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

【问题讨论】:

    标签: c c99 unions


    【解决方案1】:

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

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

    在设置不同的成员后,访问qsingleqdoubleqfloat 成员肯定会出现问题。这些成员可能具有导致引发诸如SIGFPE 之类的信号的表示,并且从此类信号处理程序返回是未定义的行为。

    【讨论】:

      【解决方案2】:

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

      [FF|01] < a uint16
      

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

      [FF|01]
           ^ read    
      ^ ignored
      

      float 解释为int 或反之亦然不太可能奏效,因为基础位没有意义:

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

      【讨论】:

      • 好的,谢谢。我不打算从浮点数转换为 r,只是整数。如果它像你说的那样是特定于编译器的,我想我会避免它。
      猜你喜欢
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 2014-07-29
      • 1970-01-01
      • 2017-02-07
      • 2019-05-01
      相关资源
      最近更新 更多