如何轻松访问工会的有效价值?

时间:2018-04-20 09:37:26

标签: c struct types unions

如何访问工会的有效值?

例如,如果我有这样的联盟:

typedef union               u_signed_identifier{
 char                       i_char;
 int                        i_int;
}                           t_signed_identifier;

我将值14赋给我的union中包含的int变量:

t_signed_identifier example;
example.i_int = 14;

我想访问该值而无需调用我的int变量。

例如:

printf("my value = %d\n", example);

当我使用gcc编译时,此示例显示警告。

是否有办法访问该值,而不使用指示活动值类型的标志?

3 个答案:

答案 0 :(得分:1)

不,你不能。工会不知道最后使用的类型。您必须使用普通的旧整数或添加标志机制。

答案 1 :(得分:0)

C标准中没有任何内容表明工会有活跃的成员。相反,对联合的任何成员执行的任何操作将同时在使用同一存储的所有成员上执行。具有“活动成员”的工会的概念是编译器编写者试图将“有效类型”规则(模棱两可,以至于比没有用的更糟)应用到工会的结果,尽管工会及其成员已经宣布了这一事实类型。

在使用通用浮点类型的平台的非钝性实现上,给出了类似的联合:

union UF {
  uint32_t u;
  float f;
} uf;

将1.0f写入uf.f然后读取uf.u的效果是采用与1.0f [hex 00 00 00 40],IIRC相关的字节序列并将其解释为uint32_t ,产生0x40000000。增加该值并将其写回将使并集保持字节序列01 00 00 40,然后读取u.f将产生与该位模式相关的float值,即1.00000006f。

在任何时间点,uf.fuf.u都将具有值,并且在高质量的通用实现中,将1.00000006f写入{{1 }}将uf.f写入0x40000001后与Universe相同。因此,除非有人手动跟踪是哪个成员,否则不可能打印出所写的并集的最后一个成员的值。

请注意,在许多情况下(其中包括),该标准没有尝试禁止“一致”的实现以钝性或无用的方式表现。根据该标准,任何访问uf.uuf.f的尝试都会调用UB,因为这样的访问将使用类型uf.ufloat的左值来访问对象。类型uint32_t,钝的实现可以以其认为合适的任何方式处理此类访问。

gcc和clang的维护者发明了以“有效类型”规则为模型的“活动工会成员”的概念,并且可能不识别尝试读取或取得活动会员以外的工会成员地址的尝试。对于编译器而言,可靠地跟踪活动的并集成员并不比跟踪有效类型更实际,并且它们的行为最终仅符合标准对使用 any 的代码没有任何要求的程度非字符类型的工会成员。

答案 2 :(得分:-1)

您无法单独使用结构或联合标识符来获取值。此外,您无法知道最后使用的是哪种类型。因为联合包含许多类型中的一种 - 它一次包含多种类型。任何尝试使用union作为包含多个不相关类型的“变体”的尝试很可能源于错误的程序设计(“XY问题”)。

您唯一能做的就是使用指向联合中包含的最大类型的指针,例如

printf("my value = %d\n", *(int*)&example);

然而,这没有明显的好处

printf("my value = %d\n", example.i_int);

(请注意,在某些情况下,像这样的指针技巧可能是危险的。存在“严格指针别名”的问题,它不适用于联合,但可以应用于结构。)