Почему "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 представляет собой последовательность деклараторов, разделенных запятыми, каждая из которых может иметь дополнительную информацию о типе, или инициализатор, или и то, и другое. Декларации содержат идентификаторы (если есть).
Обратите внимание на слова, если они есть.