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)
现在test
和tp
指相同类型(一种的结构中,一个一个指向结构),并且类似地result
并且result_ptr
指的是相同的类型,并且初始化和分配都很好,但两种类型是不同的.你不清楚是否要创建任何一种类型的复合文字 - 你必须编写(struct {int x; int y;}){.y = 9, .x = 8}
,但struct-declaration-list的存在意味着它是另一种新类型.
如评论中所述,还有第6.2.7节兼容类型和复合类型,其中说:
1...此外,如果它们的标签和成员满足以下要求,则在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都在其各自的翻译单元内的任何地方完成,则以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对相应的成员被宣布为兼容类型; 如果使用对齐说明符声明该对中的一个成员,则使用等效的对齐说明符声明另一个成员; 如果该对的一个成员使用名称声明,则另一个成员使用相同的名称声明.对于两个结构,相应的成员应按相同的顺序声明.对于两个结构或联合,相应的位域应具有相同的宽度.
粗略地说,如果两个翻译单元中的类型的定义(认为'源文件'加上包含的标题)是相同的,那么它们指的是相同的类型.感谢老天爷!否则,您可能无法使用标准I/O库,以及其他一些细节.
250*_*501 13
变量&test
和test_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中描述了声明符.此外,如果它们的标记和成员满足以下要求,则在单独的转换单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都在其各自的翻译单元内的任何地方完成,则以下附加要求适用:其成员之间应存在一对一的对应关系,以便每对相应的成员被宣布为兼容类型; 如果使用对齐说明符声明该对中的一个成员,则使用等效的对齐说明符声明另一个成员; 如果该对的一个成员使用名称声明,则另一个成员使用相同的名称声明.对于两个结构,相应的成员应按相同的顺序声明.对于两个结构或联合,相应的位域应具有相同的宽度.对于两个枚举,相应的成员应具有相同的值.