C中的兼容类型和结构
我有以下代码:
int main(void) { struct { int x; } a, b; struct { int x; } c; struct { int x; } *p; b = a; /* OK */ c = a; /* Doesn't work */ p = &a; /* Doesn't work */ return 0; }
无法在GCC(3.4.6)下编译,并出现以下错误:
test.c:8: error: incompatible types in assignment test.c:9: warning: assignment from incompatible pointer type
现在,根据我的理解(诚然来自C99标准), a
和c
应该是兼容类型,因为它们符合6.2.7节第1段中的所有标准。我尝试用std=c99
进行编译,徒劳无功。
想必我对标准的解释是错误的?
附录
顺便说一句,出现这个问题是因为我想声明一些类似模板的宏来包装各种数据类型而不必在任何地方声明命名类型/ typedef的开销,例如一个简单的例子:
#define LINKED_LIST(T) \ struct { \ T *pHead; \ T *pTail; \ } ... LINKED_LIST(foo) list1; LINKED_LIST(foo) list2; ... LINKED_LIST(foo) *pList = &list1; /* Doesn't work */
看一下规范草案,我猜你依赖于声明之后的条件:
此外,如果标签和成员满足以下要求,则在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的…
我认为这些都在同一个C文件中被删除的事实意味着它们在一个翻译单元中。
猜测似乎这可以保证当两个C文件包含一个声明类型的头时,那么该类型的实例将是兼容的。
struct { int x; }
struct { int x; }
是一个匿名结构标记,两个匿名结构不能具有“相同名称”,这是类型兼容性的必要条件。 您可以使用typedef
声明与非匿名结构兼容的类型。
struct tmp { int x; }; // declare structure tag typedef struct tmp type1; typedef struct tmp type2; // declare 3 types compatible with struct tmp typedef struct tmp type3; // and with each other type1 a, b; type2 c; type3 *p; b = a; c = a; p = &a;
结构,联合和枚举的兼容性
在单个源文件中,每个结构或联合定义都会创建一个既不与任何其他结构或联合类型相同也不兼容的新类型。 但是,类型说明符是对先前定义的结构或联合类型的引用,它们是相同的类型。 标记将引用与定义相关联,并有效地充当类型名称。 为了说明这一点,在这个例子中只有结构类型j和k兼容:
struct { int a; int b; } h; struct { int a; int b; } i; struct S { int a; int b; } j; struct S k;
可以将相容的结构彼此分配。
有趣的是Clang给出了以下内容:
error: incompatible type assigning 'struct ', expected 'struct ' warning: incompatible pointer types assigning 'struct *', expected 'struct *'
似乎如果声明了两个(或更多)匿名结构,那么编译器会执行一些内部魔术,它指定哪个特定的匿名结构也被引用。
考虑到第6.2.7段(兼容类型)和6.5.16.1(分配规则),我理解与您相同。
似乎你的代码GCC表现得像你的结构定义用不同的标签标记(事实并非如此)。 在这种情况下,类型不兼容。 但它仍然看起来像一个gcc bug。
来自其他编译器的反馈是否符合C99标准?