我有以下代码:
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 */
答案 0 :(得分:9)
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;
答案 1 :(得分:8)
看着draft specification我猜你是在依赖声明之后的条件:
此外,如果标签和成员满足以下要求,则在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的...
我认为这些都在同一个C文件中被删除的事实意味着它们在一个翻译单元中。
据猜测,这似乎可以保证当两个C文件包含一个声明类型的标头时,那个类型的实例将是兼容的。
答案 2 :(得分:3)
Compatibility of structures, unions, and enumerations
在单个源文件中,每个结构或联合定义 创建一个既不与any也不兼容的新类型 其他结构或联合类型。但是,类型说明符是 对先前定义的结构或联合类型的引用是相同的 类型。标签将引用与定义相关联,并且 有效地充当类型名称。为了说明这一点,只有类型 结构j和k在这个例子中兼容:
struct { int a; int b; } h; struct { int a; int b; } i; struct S { int a; int b; } j; struct S k;
可以相互分配兼容的结构。
答案 3 :(得分:1)
有趣的是Clang给出了以下内容:
error: incompatible type assigning 'struct <anonymous>', expected 'struct <anonymous>'
warning: incompatible pointer types assigning 'struct <anonymous> *', expected 'struct <anonymous> *'
似乎如果声明了两个(或更多)匿名结构,那么编译器会执行一些内部魔术,它指定了哪个特定的匿名结构也被引用。
答案 4 :(得分:-1)
考虑到第6.2.7段(兼容类型)和6.5.16.1(分配规则),我理解与您相同。
似乎您的代码GCC的行为就像您的结构定义用不同的标签标记(事实并非如此)。在这种情况下,类型不兼容。但它仍然看起来像一个gcc bug。
其他编译器的反馈是否符合C99标准?