#include <stdio.h> #include <stdlib.h> #include <string.h> struct a { struct a *next; int i; }; struct b { struct b *next; int i; }; struct c { int x,x2,x3; union { struct a a; struct b b; } u; }; void foo(struct b *bar) { bar->next->i = 9; return; } int main(int argc,char *argv[]) { struct c c; memset(&c,sizeof c); c.u.a.next = (struct a *)calloc(1,sizeof(struct a)); foo(&c.u.b); printf("%d\n",c.u.a.next->i); return 0; }@H_502_3@C和C有合法吗?我已经阅读过类型打击,但我不明白. foo(& c.u.b)与foo((struct b *)& c.u.a)有什么不同吗?他们不会完全一样吗?联盟中的结构体的这个异常(来自3.3.2.3中的C89)说:
If a union contains several structures that share a common initial
sequence,and if the union object currently contains one of these
structures,it is permitted to inspect the common initial part of any
of them. Two structures share a common initial sequence if
corresponding members have compatible types for a sequence of one or
more initial members.在union中,struct a的第一个成员是struct a * next,struct b的第一个成员是struct b * next.正如你可以看到一个指向struct的指针一个* next被写入,然后在foo中,一个指向struct b * next的指针被读取.它们是兼容类型吗?它们都是指向一个结构体的指针,并且指向任何结构体的指针应该是相同的大小,所以它们应该是兼容的,并且布局应该是一样的吗?从一个结构体读取i并写入另一个可以吗?我是否犯了任何类型的混淆或类型违规行为?
解决方法
struct a和struct b不兼容类型.即使在
typedef struct s1 { int x; } t1,*tp1; typedef struct s2 { int x; } t2,*tp2;@H_502_3@s1和s2是不兼容的类型. (见6.7.8 / p5中的示例)识别不兼容结构的一种简单方法是,如果两个结构类型兼容,那么一种类型的东西可以分配给另一种类型的东西.如果您希望编译器在尝试执行此操作时抱怨,则它们不兼容类型.
因此,struct a *和struct b *也不兼容类型,因此struct a和struct b不共享一个共同的初始子序列.而在其他情况下,你们的工会处罚是由同样的工会处罚规则(6.5.2.3脚注95):
If the member used to read the contents of a union object is not the
same as the member last used to store a value in the object,the
appropriate part of the object representation of the value is
reinterpreted as an object representation in the new type as described
in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be
a trap representation.在C中,struct a和struct b也不共享共同的初始子序列. [class.mem] / p18(引用N4140):
Two standard-layout structs share a common initial sequence if
corresponding members have layout-compatible types and either neither
member is a bit-field or both are bit-fields with the same width for a
sequence of one or more initial members.[basic.types] / P9:
If two types
T1
andT2
are the same type,thenT1
andT2
are
layout-compatible types. [ Note: Layout-compatible enumerations are described in 7.2. Layout-compatible standard-layout structs and
standard-layout unions are described in 9.2. —end note ]struct a *和struct b *既不是结构体,也不是联合体,也不是枚举;因此,如果它们是相同的类型,那么它们只是布局兼容的,而不是它们.
确实([basic.compound] / p3)
Pointers to cv-qualified and cv-unqualified versions (3.9.3) of
layout-compatible types shall have the same value representation and
alignment requirements (3.11).但这并不意味着这些指针类型是与layout兼容的类型,因为该术语在标准中定义.