如果我有以下代码:
#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中是合法的。
答案 0 :(得分:2)
这个问题的答案在C99 或 C11中没有明确定义。在这两个标准中,§6.2.6.1p7说:
当一个值存储在union类型的对象的成员中时, 对象表示的字节与该对应的字节不对应 成员,但确实对应其他成员采取未指定的值。
在设置不同的成员后,我肯定会发现访问qsingle
,qdouble
和qfloat
成员时遇到问题。这些成员可能具有导致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