为什么 'int ;' 在 C 中编译良好,但在 C++ 中编译不行?

Why does `int ;` compile fine in C, but not in C++?

提问人:Destructor 提问时间:10/22/2015 最后编辑:Peter MortensenDestructor 更新时间:10/24/2015 访问量:4910

问:

请考虑以下程序(在此处查看现场演示)。

#include <stdio.h>
int main(void)
{
      int ;  // Missing variable name
      puts("Surprise");
}

我的编译器 gcc 4.8.1 给出以下警告:

[警告] 空声明中的无用类型名称 [默认启用]

为什么它编译良好?我不应该得到编译器错误吗?g++ 4.8.1 在我将其编译为 C++ 程序时出现以下错误:

[错误] 声明不声明任何内容 [-fpermissive]

C++ C GCC 语言律师 变量声明

评论

1赞 Destructor 10/22/2015
@Nawaz:语言规范是明确说明的吗?
3赞 Igor Tandetnik 10/22/2015
C++ 标准明确指出:“[dcl.dcl]/5简单声明中,只有在声明类(子句 9)或枚举 (7.2) 时,即当 decl-specifier-seq 包含类说明符、带有类键详细说明类型说明符 (9.1) 或枚举说明符时,才能省略可选的 init-declarator-list ."我对 C 标准不够熟悉,无法引用章节和诗句。
33赞 n. m. could be an AI 10/22/2015
“产生警告”不是“编译良好”。
8赞 Luaan 10/22/2015
好吧,您可以同时定义多个局部变量(),对吧? 只是看起来像是同一件事的特例,有 0 个声明的当地人:Dint a, b, c;int ;
2赞 David Conrad 10/23/2015
重新编译为-Werror

答:

18赞 Yu Hao 10/22/2015 #1

声明的语法定义为(省略 init-declarator-listinit-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

请注意,声明说明符是递归定义的,但每个带有 opt 的说明符都表示它是可选的。

此外,以下第 6 条规定:

声明说明符由一系列指示链接的说明符组成, 存储持续时间,以及声明符所表示的实体类型的部分。initdeclarator-list 是以逗号分隔的声明符序列,每个声明符可能具有其他类型信息和/或初始值设定项。声明符包含要声明的标识符(如果有)。

请注意单词(如果有)。

50赞 n. m. could be an AI 10/22/2015 #2

C标准说

除static_assert声明外,声明应至少声明一个声明符(函数的参数或结构或联合的成员除外)、标记或枚举的成员。

C++ 说

在简单声明中,只有在声明类(子句 9)或枚举时,才能省略可选的 init-declarator-list。

在任何一种语言中,违反这一点都需要诊断。这些标准不讨论编译器错误或警告。警告是一种诊断。

评论

0赞 Damian Yerrick 10/22/2015
您能否澄清一下该标准是否要求翻译在某些违规行为中失败?“错误”可以定义为产生诊断和失败的冲突,而“警告”是产生诊断但未失败的冲突。
4赞 n. m. could be an AI 10/22/2015
@tepples 不,该标准仅要求诊断。它不要求(但允许)拒绝无效程序。
1赞 n. m. could be an AI 10/24/2015
这意味着例如 声明一个 struct 成员,但这还不够。struct { int a; };
0赞 Destructor 10/24/2015
@n.M.:所以这里需要结构名称。右?
1赞 n. m. could be an AI 10/24/2015
需要标记或声明符。标记是 。声明器是 。声明符可以是变量名称,也可以是 typedef 名称(如果有 typedef 关键字)。struct a { ... }struct { ...} a
36赞 AnT stands with Russia 10/22/2015 #3

您的代码在 C 和 C++ 中都是非法的(即错误、格式错误、违反约束)。在一种语言中收到“警告”而在另一种语言中收到“错误”的原因只是编译器和编译器设置的一个怪癖。毕竟,这两种语言都没有真正正式区分“警告”和“错误”。默认设置下的 GCC 恰好在 C 模式下更宽松(主要是出于历史原因)。

在 GCC 中使用,您也会在 C 代码中得到“错误”。(请注意,不要简单地盲目地将所有“警告”变成“错误”。它尝试仅将实际的约束冲突报告为“错误”。-pedantic-errors-pedantic-errors