58
votes

Consider the following program (see live demo here).

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

My compiler, gcc 4.8.1, gives the below warning:

[Warning] useless type name in empty declaration [enabled by default]

Why does it compile fine? Shouldn't I get a compiler error? g++ 4.8.1 gives the following error when I compile it as a C++ program:

[Error] declaration does not declare anything [-fpermissive]

3
@Nawaz: Is it explicitly said by language specification? - Destructor
It is explicitly said by the C++ standard: "[dcl.dcl]/5 In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (Clause 9) or enumeration (7.2), that is, when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier with a class-key (9.1), or an enum-specifier." I'm not familiar with the C standard sufficiently well to cite chapter and verse. - Igor Tandetnik
"produces warning" is not "compiles fine". - n. 1.8e9-where's-my-share m.
Well, you can define multiple locals at the same time (int a, b, c;), right? int ; just looks like a special case of the same thing, with 0 declared locals :D - Luaan
Recompile with -Werror - David Conrad

3 Answers

48
votes

The C standard says

A declaration other than a static_assert declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.

C++ says

In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (Clause 9) or enumeration.

A violation of this in either language requires a diagnostic. The standards do not talk about compiler errors or warnings. A warning is a diagnostic.

34
votes

Your code is illegal (i.e. erroneous, ill-formed, constraint-violating) in both C and C++. The reason you get a "warning" in one language and "error" in another is just a quirk of your compiler and your compiler setup. After all, neither language really formally differentiates between "warnings" and "errors". GCC under its default settings just happens to be more permissive in C mode (mostly for historical reasons).

Use -pedantic-errors in GCC, and you will get an "error" in C code as well. (Note that -pedantic-errors does not simply blindly turn all "warnings" into "errors". It attempts to report only actual constraint violations as "errors".)

18
votes

The syntax of declaration is defined as (omitting init-declarator-list and init-declarator):

C11 6.7 Declarations

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

Note that declaration-specifiers is defined recursively, but each with an opt indicates it's optional.

Also, the following clause 6 states:

The declaration specifiers consist of a sequence of specifiers that indicate the linkage, storage duration, and part of the type of the entities that the declarators denote. The initdeclarator-list is a comma-separated sequence of declarators, each of which may have additional type information, or an initializer, or both. The declarators contain the identifiers (if any) being declared.

Note the words if any.