考虑以下计划(参见现场演示here)。
#include <stdio.h>
int main(void)
{
int ; // Missing variable name
puts("Surprise");
}
我的编译器gcc 4.8.1给出了以下警告:
[警告]空声明中的无用类型名称[默认启用]
为什么编译正常?难道我不会遇到编译错误吗?当我将它编译为C ++程序时,g ++ 4.8.1给出以下错误:
[错误]声明未声明任何内容[-fpermissive]
答案 0 :(得分:48)
C标准说
除static_assert声明之外的声明应至少声明一个声明符(除了函数的参数或结构或联合的成员),标记或枚举的成员。
C ++说
在一个简单声明中,只有在声明一个类(第9节)或枚举时,才能省略可选的init-declarator-list。
在任何一种语言中违反此要求都需要诊断。标准不讨论编译器错误或警告。警告是诊断。
答案 1 :(得分:34)
您的代码在C和C ++中都是非法的(即错误,格式错误,违反约束)。您在一种语言中获得“警告”而在另一种语言中获得“错误”的原因只是编译器和编译器设置的一个怪癖。毕竟,这两种语言都没有真正正式区分“警告”和“错误”。 GCC在其默认设置下恰好在C模式下更加宽松(主要是出于历史原因)。
在GCC中使用-pedantic-errors
,您也会在C代码中收到“错误”。 (请注意,-pedantic-errors
不会盲目地将所有“警告”变为“错误”。它会尝试仅将实际的约束违规行为报告为“错误”。)
答案 2 :(得分:18)
声明的语法定义为(省略 init-declarator-list 和 init-declarator ):
C11 6.7声明
declaration: declaration-specifiers init-declarator-list opt ; static_assert-declaration declaration-specifiers: storage-class-specifier declaration-specifiers opt type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt function-specifier declaration-specifiers opt alignment-specifier declaration-specifiers opt
请注意, declaration-specifiers 是递归定义的,但每个 opt 表示它是可选的。
此外,以下第6条规定:
声明说明符由一系列指示链接的说明符组成, 存储持续时间,以及声明者表示的实体类型的一部分。 initdeclarator-list是一个以逗号分隔的声明符序列,每个声明符都可以包含其他类型信息,或初始值设定项,或两者兼而有之。声明者包含声明的标识符(如果有的话)。
请注意字样。