我有以下代码:
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; }
是匿名结构体标签,两个匿名结构体不能有“同名”,这是类型兼容的必要条件。您可以使用 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 <anonymous>', expected 'struct <anonymous>'
warning: incompatible pointer types assigning 'struct <anonymous> *', expected 'struct <anonymous> *'
似乎如果声明了两个(或更多)匿名结构,那么编译器会执行一些内部魔法,指定也引用了哪个特定的匿名结构。
考虑第6.2.7段(兼容类型)和6.5.16.1(赋值规则),我的理解和你一样。
看起来你的代码 GCC 的行为就像你的结构定义用不同的标签标记一样(事实并非如此)。在这种情况下,类型将不兼容。然而它看起来仍然像一个 gcc bug。
其他实现 C99 标准的编译器有任何反馈吗?