尽管结构中的char* name声明没有分号,但下面的代码仍被成功编译。
#include<stdio.h>
typedef struct map
{
int id;
char *name
}map;
int main()
{
return 0;
}
发布于 2017-09-11 15:52:01
我怀疑这个问题可能与C11标准有关(我没有更旧的版本,但它可能是相同的),其中指定(6.7.2.1第8段):
在结构或联合说明符中出现结构声明列表将在转换单元中声明一个新类型。struct声明列表是结构或联合的成员的声明序列。如果struct声明列表不包含任何命名成员,无论是直接还是通过匿名结构或匿名联合,行为都是未定义的。直到紧跟在终止列表的
}
之后,该类型才是不完整的,并且在之后完成。
这意味着正在执行两个操作:
列表的联合终止(类型(结构或struct-declaration-list).
我认为这可以(错误地)构造为意味着}
可以通过充当终止结构声明节点的分号闭包来终止结构声明列表。
否则,有人可能会争辩说,应该只有一个操作(类型的完成),而不是两个(结构声明列表的终止+类型的完成)。
这种允许的解释(可能不反映作者的意图,IMHO)使这成为一个有问题的允许语言解释功能,而不是一个问题。
无论采用哪种方式,clang
和gcc
的当前版本都会在缺少分号时报告(当使用c11标志时)。这显示了行为的一致性,这表明这是对标准的解释,而不是bug。
考虑到这种可能的歧义,以及声明后的}
没有留下代码含义的问题,我认为编译器开发人员倾向于发出警告而不是错误绝对是合法的,并且不需要错误报告。
编辑
我阅读了John Bode的答案和Olaf的评论,并相应地编辑了我的答案,以使我的观点更加清晰。
虽然John和Olaf都比我聪明得多,虽然我从他们的角度看到了优点,但我认为在这一点上标准还不够清楚。
的确,约翰回答中的详细引用定义了每个struct-declaration
都以分号(;
)结束,这意味着列表应该以分号结束。
然而,同一部分中的文本解释似乎表明}
可能具有双重功能。
这个建议的解释空间可能太宽松了,然而,这是在编译代码(IMHO)时引发警告而不是错误的充分理由-特别是因为代码本身不会被误解。
https://stackoverflow.com/questions/46159108
复制