C - 不兼容的指针类型

Eri*_*k W 26 c struct pointers initialization incompatibletypeerror

为什么以下代码会发出警告?

int main(void)
{
    struct {int x; int y;} test = {42, 1337};
    struct {int x; int y;} *test_ptr = &test;
}
Run Code Online (Sandbox Code Playgroud)

结果:

warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
         struct {int x; int y;} *test_ptr = &test;
                                            ^
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 33

它们是两种匿名结构类型(它们都没有标签).所有这些结构类型(在单个翻译单元中)都是不同的 - 它们永远不是同一类型.添加标签!

标准中的相关句子在§6.7.2.1 结构和联合说明符中:

8一个的存在结构声明列表结构,或工会说明符声明了一个新的类型,一个翻译单元内.

结构声明列表是指材料之间{,并}在类型.

这意味着在您的代码中,有两种不同的类型,每种类型一种struct { … }.这两种类型是分开的; 你不能正式地将一种类型的值分配给另一种,也不能创建指针等.事实上,你不能在分号后再次引用这些类型.

这意味着你可以:

int main(void)
{
    struct {int x; int y;} test = {42, 1337}, *tp = &test;
    struct {int x; int y;} result, *result_ptr;
    result_ptr = &result;
    …
}
Run Code Online (Sandbox Code Playgroud)

现在testtp指相同类型(一种的结构中,一个一个指向结构),并且类似地result并且result_ptr指的是相同的类型,并且初始化和分配都很好,但两种类型是不同的.你不清楚是否要创建任何一种类型的复合文字 - 你必须编写(struct {int x; int y;}){.y = 9, .x = 8},但struct-declaration-list的存在意味着它是另一种新类型.

如评论中所述,还有第6.2.7节兼容类型和复合类型,其中说:

1...此外,如果它们的标签和成员满足以下要求,则在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都在其各自的翻译单元内的任何地方完成,则以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对相应的成员被宣布为兼容类型; 如果使用对齐说明符声明该对中的一个成员,则使用等效的对齐说明符声明另一个成员; 如果该对的一个成员使用名称声明,则另一个成员使用相同的名称声明.对于两个结构,相应的成员应按相同的顺序声明.对于两个结构或联合,相应的位域应具有相同的宽度.

粗略地说,如果两个翻译单元中的类型的定义(认为'源文件'加上包含的标题)是相同的,那么它们指的是相同的类型.感谢老天爷!否则,您可能无法使用标准I/O库,以及其他一些细节.


250*_*501 13

变量&testtest_ptr匿名结构具有不同的类型.

在同一翻译单元中定义的匿名结构永远不会与类型1兼容,因为标准没有为同一翻译单元中的两个结构类型定义定义兼容性.

要编译代码,您可以:

struct {int x; int y;} test = {42, 1337} , *test_ptr;
test_ptr = &test;
Run Code Online (Sandbox Code Playgroud)

1(引用自:ISO:IEC 9899:201X 6.2.7兼容类型和复合类型1)
如果类型相同,则两种类型具有兼容类型.用于确定两种类型是否兼容的附加规则在6.7.2中描述了类型说明符,在6.7.3中描述了类型限定符,在6.7.6中描述了声明符.此外,如果它们的标记和成员满足以下要求,则在单独的转换单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都在其各自的翻译单元内的任何地方完成,则以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对相应的成员被宣布为兼容类型; 如果使用对齐说明符声明该对中的一个成员,则使用等效的对齐说明符声明另一个成员; 如果该对的一个成员使用名称声明,则另一个成员使用相同的名称声明.对于两个结构,相应的成员应按相同的顺序声明.对于两个结构或联合,相应的位域应具有相同的宽度.对于两个枚举,相应的成员应具有相同的值.