Przeglądając gramatykę BNF języka C, pomyślałem, że to dziwne, że reguła produkcyjna deklaracji wygląda tak (zgodnie z https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20 Backus-Naur% 20form.htm ):
<declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ;
Po co używać *
kwantyfikatora (co oznacza zero lub więcej wystąpień) dla init-declarator
? Dzięki temu instrukcje takie jak int;
lub void;
mogą być poprawne pod względem składniowym, nawet jeśli są semantycznie niepoprawne. Czy nie mogli po prostu zastosować +
kwantyfikator (jedno lub więcej wystąpień) zamiast *
w regule produkcyjnej?
Próbowałem skompilować prosty program, aby zobaczyć, co wyprowadza kompilator, i wszystko, co robi, to ostrzeżenie.
Wejście:
int main(void) {
int;
}
Wynik:
test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
int;
^~~
c
language-lawyer
context-free-grammar
rafaelfp
źródło
źródło
int
jako typu zwrotu dlamain
i nie używaj()
jako listy typów parametrów w funkcjach, ale(void)
zamiast tego.Odpowiedzi:
declaration-specifier
obejmujetype-specifier
, co obejmujeenum-specifier
. Konstrukt jakjest ważny
declaration
bezinit-declarator
.Konstrukcje takie
int;
są wykluczone przez ograniczenia wykraczające poza gramatykę :Sądzę, że istnieją kompilacje wstecznej kompatybilności, które powodują, że Twój kompilator wydaje tylko ostrzeżenie.
źródło
Deklaracja bez deklaratora init:
jest nieszkodliwy dla list specyfikatorów deklaracji, które nie są pojedynczymi specyfikatorami
enum
/struct
/union
i użytecznie pasuje do tych, które są.W każdym razie prezentowana gramatyka będzie również błędnie dopasowywać deklaracje takie jak
int struct foo x;
lubdouble _Bool y;
(pozwala wielu specyfikatorom w celu dopasowania rzeczy takich jaklong long int
), ale wszystkie te można wykryć później, w ramach kontroli semantycznej.Sama gramatyka BNF nie usunie wszystkich nielegalnych konstrukcji.
źródło