Warum erlaubt die BNF-Grammatik von C Deklarationen mit einer leeren Folge von Init-Deklaratoren?

Lesezeit: 3 Minuten

Benutzer-Avatar
raffaelfp

Als ich die BNF-Grammatik von C durchgesehen habe, fand ich es seltsam, dass die Produktionsregel für eine Deklaration so aussah (lt https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of%20C%20in%20Backus-Naur%20form.htm):

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

Warum ein verwenden * Quantifizierer (d. h. null oder mehr Vorkommen) für die init-declarator? Damit lassen sich Aussagen wie z int; oder void; syntaktisch gültig sein, obwohl sie semantisch ungültig sind. Hätten sie nicht einfach a benutzen können + Quantifizierer (ein oder mehrere Vorkommen) statt * in der Produktionsregel?

Ich habe versucht, ein einfaches Programm zu kompilieren, um zu sehen, was der Compiler ausgibt, und alles, was er tut, ist eine Warnung auszugeben.

Eingang:

int main(void) {
    int;
}

Ausgabe:

test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
     int;
     ^~~

  • Der Unterschied besteht darin, dass die BNF nur die Syntax definiert. Ziemlich viele Dinge sind syntaktisch erlaubt, aber immer noch ungültig (oder absurd) C. Aber netter Fund!

    – ljrk

    4. April 2020 um 10:21 Uhr

  • Ah, und bitte verwenden int als Rückgabetyp für main und nicht verwenden () als Parametertypenliste in Funktionen aber (void) stattdessen.

    – ljrk

    4. April 2020 um 10:22 Uhr

  • Konzeptionelldaran ist nichts wirklich auszusetzen, außer dass es ein bisschen komisch klingt: Es fragt den Computer im Grunde: “Ich möchte bitte Null-Int-Variablen, Namen: [emptyset].”. Sie können schließlich jemanden um null Äpfel bitten (obwohl es wahrscheinlich eine etwas interessantere Reaktion hervorrufen wird, als nach einem zu fragen, aber es ist keine von Natur aus unsinnige Aussage). Warum sollte es also in C ungrammatisch sein? Es gibt nichts falsch mit dieser Art von Grammatik.

    – Der_Sympathisant

    5. April 2020 um 3:42 Uhr

  • Sehr oft funktionieren die Dinge sowieso viel besser, wenn wir den leeren (oder vielleicht Vakuum?) Fall einbeziehen.

    – Der_Sympathisant

    5. April 2020 um 3:43 Uhr

  • Manchmal schreibt kein Mensch ein Programm, sondern ein anderes Programm. Ein solches Programm möchte manchmal “int” ausgeben, gefolgt von einer durch Kommas getrennten Liste der benötigten Evarnamen, gefolgt von “;” und freuen Sie sich, nicht zuerst prüfen zu müssen, ob die Liste leer ist.

    – Hagen von Eitzen

    5. April 2020 um 6:21 Uhr

Benutzer-Avatar
Benutzer2357112

declaration-specifier beinhaltet type-specifierwelches beinhaltet enum-specifier. Ein Konstrukt wie

enum stuff {x, y};

ist gültig declaration ohne init-declarator.

Konstrukte wie int; sind ausgeschlossen durch Beschränkungen jenseits der Grammatik:

Eine andere Deklaration als eine static_assert-Deklaration muss mindestens einen Deklarator (anders als die Parameter einer Funktion oder die Mitglieder einer Struktur oder Vereinigung), ein Tag oder die Mitglieder einer Enumeration deklarieren.

Ich würde vermuten, dass es Abwärtskompatibilitätsgründe dafür gibt, dass Ihr Compiler nur eine Warnung ausgibt.

Eine Deklaration ohne Init-Deklarator:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

ist harmlos für Listen mit Deklarationsbezeichnern, die keine einzige sind enum/struct/union Bezeichner und passt sinnvollerweise zu denen, die sind.

In jedem Fall wird die präsentierte Grammatik auch fälschlicherweise mit Deklarationen wie übereinstimmen int struct foo x; oder double _Bool y; (Es erlaubt mehrere Spezifizierer, um Dinge wie abzugleichen long long int), aber all dies kann später in einer semantischen Prüfung erkannt werden.

Die BNF-Grammatik selbst wird nicht alle illegalen Konstrukte aussortieren.

1368090cookie-checkWarum erlaubt die BNF-Grammatik von C Deklarationen mit einer leeren Folge von Init-Deklaratoren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy