C 中的递归联合定义

Recursive union definition in C

我想制作类似二叉搜索树的东西,用于将地址映射到 Page *s(除了它实际上是十六进制的,并且地址由结构本身隐含),所以:

typedef union Map Map;
union Map {
    Map (*ps)[16];
    Page *p;
};

这在逻辑上是完全合理的(联合 Map 包含指向 Page 的指针或指向 16 Maps 的数组的指针),但是 gcc 错误在ps 声明与 array type has incomplete element type,所以我猜这种递归定义在 C 中是不允许的。

有没有什么方法可以在不使用指针别名等技巧的情况下做到这一点?

C 2018 6.7.6.2 1 指定数组声明符的约束。它说,部分:

The element type shall not be an incomplete or function type.

Map (*ps)[16]中,(*ps)[16]是一个声明符,如6.7.6的语法所示 1.由于它是一个数组声明符,所以它受6.7.6.2规则约束,因此元素类型必须完整。即使声明的最终类型是指针也是如此。

如评论中所述,您可以改为声明 Map *ps。如果这不能令人满意,因为 ps 上的指针算法以 Map 为单位而不是 Map [16],另一种方法是在联合之前定义 typedef struct Map16 Map16;,然后 Map16 *ps; 在联合内,然后在联合后 struct Map16 { Map element[16]; } 。这将使 ps 上的指针算法以所需的单位工作(假设实现不填充结构,这将是不寻常的),尽管它确实使您在引用元素时使用额外的 .element

考虑为什么 Map *ps 被接受而 Map (*ps)[16] 不被接受,我们可以看到两者都声明了指向不完整类型的指针,因此区分的不是指向类型的完整性它们只是 C 标准中的这条规则。可能是 6.7.6.2 1 中的规则可能已被修改为允许 Map (*ps)[16],因为编译器此时似乎不需要有关指向类型的完整信息。