你可以用 C11:
§ 6.7.2.1 -- 11
类型说明符是没有标记的结构说明符的未命名成员称为
匿名结构;一个未命名的成员,其类型说明符是一个联合说明符
没有标签称为匿名联合。匿名结构或联合的成员
被认为是包含结构或联合的成员。这适用
如果包含结构或联合也是匿名的,则递归。
所以这段代码可能工作:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct { foo; } bar;
int main(void)
{
bar b;
b.x = 1;
printf("%d\n", b.x);
}
这里的问题是,不同的编译器在我的测试中对于 typedef 是否可以作为没有标签的 struct 说明符是可以接受的 标准规定:
§ 6.7.8 -- 3
在存储类说明符为typedef 的声明中,每个声明符定义一个
identifier 是一个 typedef 名称,表示为该标识符指定的类型
在 6.7.6 中描述。 [...] typedef 声明没有引入新类型,只有 a
指定类型的同义词。
(强调我的)——但是 synonym 是否也意味着 typdef-name 说明符可以替换为 struct 说明符? gcc 接受,clang 不接受。
当然,没有办法用这些声明表达foo类型的整个成员,你牺牲了你的命名成员f。
关于您对名称冲突的疑问,这是gcc 在您将另一个int x 放入bar 时必须说的:
structinherit.c:4:27: error: duplicate member 'x'
typedef struct { foo; int x; } bar;
^
为避免歧义,您可以重复结构,可能将#defined 作为宏,但当然,这看起来有点难看:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct { struct { int x; }; } bar;
int main(void)
{
bar b;
b.x = 1;
printf("%d\n", b.x);
}
但是任何符合标准的编译器都应该接受这个代码,所以坚持这个版本。
很遗憾,我更喜欢gcc 接受的语法,但由于标准的措辞并没有明确允许这样做,唯一的安全的赌注是假设它是被禁止的,所以clang在这里不应该受到责备......
如果您想通过 either b.x 或 b.f.x 引用 x,您可以像这样使用额外的匿名联合:
#include <stdio.h>
typedef struct { int x; } foo;
typedef struct {
union { struct { int x; }; foo f; };
} bar;
int main(void)
{
bar b;
b.f.x = 2;
b.x = 1;
printf("%d\n", b.f.x); // <-- guaranteed to print 1
}
这不会因为
而导致别名问题
§ 6.5.2.3 -- 6
一个特殊的保证是为了简化联合的使用:如果联合包含多个共享一个共同初始序列的结构(见下文),并且如果联合对象当前包含这些结构之一,则允许在联合的完整类型声明可见的任何地方检查它们中任何一个的公共初始部分。如果对应的成员对于一个或多个初始成员的序列具有兼容的类型(并且对于位域,具有相同的宽度),则两个结构共享一个共同的初始序列