我有两个结构,如
struct X {
int x;
double *y;
};
struct Y {
int a;
double *b;
char c;
};
向指向struct Y
的指针投射指向struct X
的指针,保证以合理的方式保持一致(即x->x
和x->y
对应y->a
和y->b
分别按C89标准?不太重要,但如果您也碰巧知道会非常酷,这对于后来的标准也是如此(例如C11)和其他与C语法重叠和语义重叠的语言(例如C ++ XX,Objective-C )?
答案 0 :(得分:7)
这是未定义的行为。 Python relied on this before and had to fix that.如果您struct Y
包含struct X
作为其第一个元素,则可以将其用于类似效果:
struct Y {
struct X a;
char c;
};
struct Y y;
struct X *x = (struct X *) &y; /* legal! */
工会也有一个特例:
struct X {
int x;
double *y;
};
struct Y {
int a;
double *b;
char c;
};
union XY {
struct X x;
struct Y y;
};
union XY xy;
xy.x.x = 0;
printf("%d\n", xy.y.a); /* legal! */
在C标准的更高版本中,如果像这样的联合定义实际上在范围内,编译器只需要处理X
和Y
个对象别名,但在C89中,它主要是必须假设这样的定义存在于某处。但是,将struct Y *
投射到struct X *
仍然无法安全;如果编译器知道特定的struct Y
不是联合的一部分,它仍然可能认为struct X *
不可能对它进行别名。
答案 1 :(得分:2)
C89允许通过强制转换将指向一个对象类型的指针转换为指向不同对象类型的指针。
然而,在我们进行解除引用之前,只有当原始指针的引用类型需要至少与结果指针引用的类型的对齐时,才能保证转换后的指针完全有效。对齐完全取决于实现。在您的特定示例中,可能但不保证,两个struct
类型将具有相同的对齐要求。
假设转换确实产生了有效的指针,标准没有准确定义struct
成员在struct
对象的表示中的布局方式。成员必须以与struct
定义中相同的顺序出现,并且在第一个之前不得有任何填充,但不定义其他详细信息。因此,在您的示例中,保证X->x
将对应于Y->a
(再次假设转换的指针在第一位有效),但未定义X->y
是否对应到Y->b
。