【发布时间】:2015-03-11 16:44:31
【问题描述】:
C 标准规定:
一个指向结构对象的指针,经过适当的转换,指向它的初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。
如果所讨论的结构的第一个成员是匿名结构/联合,是否有任何可能(并且定义明确)的方式在 C11 中执行这种“合适的强制转换”?或者如果包含结构是匿名的,则执行“反之亦然”的反向转换?
我猜想,强制转换为具有与匿名结构相同的成员序列的非匿名结构会使其定义不明确,因为它们不兼容,因此不能保证具有相同的内存布局。
但是,C 标准规定:
而且,两种结构, 在单独的翻译单元中声明的联合或枚举类型是兼容的,如果它们的 标签和成员满足以下要求:如果使用标签声明,则 其他应使用相同的标签声明。如果两者都在其范围内的任何地方完成 相应的翻译单位,则适用以下附加要求:应 成员之间是一一对应的<...>
我们可以尝试将此规则应用于匿名结构吗?假设我们有以下设置:
header.h:
struct container {
struct {
int a;
char b;
};
};
void print(struct container *pcontainer);
sep.c:
#include <stdio.h>
#include "header.h"
void print(struct container *pcontainer){
printf("%d\n", ((struct { int a; char b; }*)pcontainer)->a);
}
main.c:
#include "header.h"
int main(void){
struct container container, *pcontainer;
pcontainer = &container;
pcontainer->a = 1;
print(pcontainer);
return 0;
}
(在 gcc (GCC) 4.8.3 20140911 上编译并输出 1)。
考虑在print 函数内的强制转换中使用的匿名结构和作为struct container 的第一个成员的匿名结构在main.c 中结束时间>。它们可以被视为“在单独的翻译单元中声明的类型”吗?另外,它们是否真的满足所有其他兼容性要求,还是我误解了什么?
【问题讨论】:
-
请注意,相同的结构总是具有相同的内存布局(至少对于可以独立编译和链接单独的源文件的实现而言),即使它们不兼容,因为可能存在是在另一个翻译单元中与它们两者兼容的另一个相同结构。这里的问题是是否违反了严格的别名。
-
@mafso:当然,我很清楚这一点。我只是对这种情况下的行为是否被标准明确定义感兴趣。
-
另外注意,这并不是关于匿名结构,而是关于没有标签的结构。所以这个问题也适用于 C99。
-
我提到的 [...] 定义不明确,因为它们不兼容,因此不能保证具有相同的内存布局。 一个实现,其中他们没有,会很做作。另一方面,严格别名可能会成为实际代码中实际实现的问题。 (而且我也很好奇这个问题,我没有质疑。)
标签: c pointers struct c11 anonymous-struct