Почему "int;" компилируется в C, но не в С++?

Рассмотрим следующую программу (см. живое демо здесь).

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

Мой компилятор gcc 4.8.1 дает следующее предупреждение:

[Предупреждение] бесполезное имя типа в пустое объявление [включено по умолчанию]

Почему он компилируется? Должен ли я получить ошибку компилятора? g++ 4.8.1 дает следующую ошибку, когда я компилирую ее как программу на С++:

Объявление [Error] не объявляет ничего [-fpermissive]

Ответ 1

В стандарте C говорится:

Объявление, отличное от объявления static_assert, должно объявлять хотя бы декларатор (кроме параметров функции или членов структуры или объединения), тега или членов перечисления.

С++ говорит

В простой декларации необязательный список init-declarator может быть опущен только при объявлении класса (раздел 9) или перечисления.

Нарушение этого на любом языке требует диагностики. Стандарты не говорят о ошибках компилятора или предупреждениях. Предупреждение является диагностическим.

Ответ 2

Ваш код является незаконным (т.е. ошибочным, плохо сформированным, нарушением ограничений) как на C, так и на С++. Причина, по которой вы получаете "предупреждение" на одном языке и "ошибка" в другом, - это просто причуда вашего компилятора и ваша настройка компилятора. В конце концов, ни один язык действительно формально не различает "предупреждения" и "ошибки" . GCC под своими настройками по умолчанию просто оказывается более разрешительным в режиме C (в основном по историческим причинам).

Используйте -pedantic-errors в GCC, и вы также получите "ошибку" в коде C. (Обратите внимание, что -pedantic-errors не просто слепо превращает все "предупреждения" в "ошибки" . Он пытается сообщать только о фактических нарушениях ограничений как "ошибки" .)

Ответ 3

Синтаксис объявления определяется как (опуская 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

Обратите внимание, что спецификаторы-объявления определены рекурсивно, но каждый с opt указывает на необязательность.

Кроме того, в следующем разделе 6 говорится:

Спецификаторы декларации состоят из последовательности спецификаторов, которые указывают связь, время хранения и часть типа объектов, обозначенных деклараторами. Список initdeclarator представляет собой последовательность деклараторов, разделенных запятыми, каждая из которых может иметь дополнительную информацию о типе, или инициализатор, или и то, и другое. Декларации содержат идентификаторы (если есть).

Обратите внимание на слова, если они есть.