Просматривая грамматику BNF в C, я подумал, что странно, что производственное правило для объявления выглядит следующим образом (согласно https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ):
<declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ;
Зачем использовать *
квантификатор (имеется в виду ноль или более вхождений) для init-declarator
? Это позволяет синтаксически допустимым операторам типа int;
или void;
быть, даже если они семантически недействительны. Разве они не могли просто использовать +
квантификатор (одно или несколько вхождений) вместо *
правила производства?
Я попытался скомпилировать простую программу, чтобы увидеть, что выводит компилятор, и все, что он делает, это выдает предупреждение.
Входные данные:
int main(void) {
int;
}
Вывод:
test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
int;
^~~
c
language-lawyer
context-free-grammar
rafaelfp
источник
источник
int
в качестве типа возврата дляmain
и не используйте()
в качестве списка типов параметров в функциях, но(void)
вместо этого.Ответы:
declaration-specifier
включает в себяtype-specifier
, который включает в себяenum-specifier
. Конструкция какявляется действительным
declaration
с нетinit-declarator
.Такие конструкции, как
int;
исключаются из грамматических ограничений :Я предполагаю, что за компилятором есть причины обратной совместимости, выдающие только предупреждение.
источник
Объявление без инициатора объявления:
безвреден для списков спецификаторов объявлений, которые не являются одиночными
enum
/struct
/union
спецификаторами, и полезны для тех, которые являются.В любом случае, представленная грамматика также будет ошибочно соответствовать объявлениям, подобным
int struct foo x;
илиdouble _Bool y;
(она позволяет использовать несколько спецификаторов для соответствия вещам вродеlong long int
), но все это может быть обнаружено позже, в семантической проверке.Сама грамматика BNF не отсеет все незаконные конструкции.
источник