将指针投射到不同的结构是否保证在 C89 中有意义?
Is casting a pointer to different structs guaranteed to be meaningful in C89?
我有两个结构像
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)?
这是未定义的行为。 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 *
不可能为它取别名。
C89 允许通过强制转换将指向一种对象类型的指针转换为指向不同对象类型的指针。
然而,在我们开始取消引用之前,仅当原始指针的引用类型要求对齐至少与结果指针引用的类型一样严格时,转换后的指针才能保证完全有效.对齐完全取决于实现。在您的特定示例中,但不能保证,两种 struct
类型可能具有相同的对齐要求。
假设转换确实产生了一个有效的指针,该标准并未准确定义 struct
成员在 struct
对象的表示中的布局方式。成员必须以与 struct
定义中相同的顺序出现,并且在第一个之前不能有任何填充,但没有定义其他细节。因此,在您的示例中,可以保证 X->x
将对应于 Y->a
(再次假设转换后的指针首先有效),但未定义 X->y
是否对应至 Y->b
.
我有两个结构像
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)?
这是未定义的行为。 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 *
不可能为它取别名。
C89 允许通过强制转换将指向一种对象类型的指针转换为指向不同对象类型的指针。
然而,在我们开始取消引用之前,仅当原始指针的引用类型要求对齐至少与结果指针引用的类型一样严格时,转换后的指针才能保证完全有效.对齐完全取决于实现。在您的特定示例中,但不能保证,两种 struct
类型可能具有相同的对齐要求。
假设转换确实产生了一个有效的指针,该标准并未准确定义 struct
成员在 struct
对象的表示中的布局方式。成员必须以与 struct
定义中相同的顺序出现,并且在第一个之前不能有任何填充,但没有定义其他细节。因此,在您的示例中,可以保证 X->x
将对应于 Y->a
(再次假设转换后的指针首先有效),但未定义 X->y
是否对应至 Y->b
.