C标准对两种相同类型的联合说了什么

时间:2013-11-07 14:38:32

标签: c types unions

是否有可能在任何架构上使用任何编译器使以下断言失败?

union { int x; int y; } u;
u.x = 19;
assert(u.x == u.y);

3 个答案:

答案 0 :(得分:6)

C99对一个联盟的两个成员是共享初始字段序列的结构的情况做出特殊保证:

struct X {int a; /* other fields may follow */ };
struct Y {int a; /* other fields may follow */ };
union {X x; Y y;} u;
u.x.a = 19;
assert(u.x.a == u.y.a); // Guaranteed never to fail by 6.5.2.3-5.
  

6.5.2.3-5:为了简化工会的使用,我们做出了一项特殊保证:如果工会包含   几个结构共享一个共同的初始序列(见下文),如果是联盟   对象当前包含这些结构中的一个,允许检查公共结构   任何一个声明完整类型的联盟的任何地方的初始部分   可见。如果相应的成员有两个结构共享一个共同的初始序列   对于一个或多个序列的兼容类型(以及对于位字段,相同的宽度)   初始成员。

但是,我无法为联盟内的非结构化类型找到可比较的保证。但这很可能是一个遗漏:如果标准用了一段时间来描述结构类型必须发生的事情,那么它应该为更简单的非结构化类型澄清相同的观点。

答案 1 :(得分:4)

问题中的assert在标准C的实现中永远不会失败,因为在分配到u.y之后访问u.x需要将u.x的字节重新解释为u.y的类型。由于类型相同,重新解释会产生相同的值。

该要求在C 2011(N1570)6.5.2.3注释95中注明,其表示它源自第6.2.6节,其涵盖了类型的表示。注95说:

  

如果用于读取union对象内容的成员与上次用于在对象中存储值的成员不同,则该值的对象表示的相应部分将被重新解释为对象表示形式。 6.2.6中描述的新类型(有时称为''punning''的过程)。这可能是陷阱表示。

(N1570是非正式的草案,但是readily available on the net。)

答案 2 :(得分:3)

我认为这个问题很难以你期望的方式回答。

据我所知,读取union的一个不是最近被写入的字段,是未定义的行为。

因此,用“否”回答是不可能的,因为任何编译器编写者都可以自由地专门检测到这一点,并且如果他们有这种感觉就会让它失败。