362 Stimmen

int a[] = {1,2,}; Warum ist ein nachgestelltes Komma in einer Initialisierungsliste zulässig?

Vielleicht bin ich nicht von diesem Planeten, aber es scheint mir, dass das Folgende ein Syntaxfehler sein sollte:

int a[] = {1,2,}; //extra comma in the end

Ist es aber nicht. Ich war überrascht, als dieser Code in Visual Studio kompiliert wurde, aber ich habe gelernt, dem MSVC-Compiler nicht zu trauen, was die C++-Regeln angeht, also habe ich den Standard überprüft, und er es auch nach der Norm zulässig. Wenn Sie mir nicht glauben, können Sie unter 8.5.1 die Grammatikregeln nachlesen.

enter image description here

Warum ist das erlaubt? Dies mag eine dumme, nutzlose Frage sein, aber ich möchte, dass Sie verstehen, warum ich frage. Wenn es sich um einen Unterfall einer allgemeinen Grammatikregel handeln würde, würde ich es verstehen - man hat beschlossen, die allgemeine Grammatik nicht noch schwieriger zu machen, nur um ein überflüssiges Komma am Ende einer Initialisierungsliste zu verbieten. Aber nein, das zusätzliche Komma ist ausdrücklich erlaubt. Zum Beispiel ist es nicht erlaubt, ein überflüssiges Komma am Ende der Argumentliste eines Funktionsaufrufs zu haben (wenn die Funktion ... ), was normal ist .

Noch einmal: Gibt es einen besonderen Grund für dieses überflüssige Komma? ausdrücklich erlaubt?

454voto

Jon Skeet Punkte 1325502

Es macht es einfacher, Quellcode zu erzeugen und auch Code zu schreiben, der später leicht erweitert werden kann. Überlegen Sie, was erforderlich ist, um einen zusätzlichen Eintrag hinzuzufügen:

int a[] = {
   1,
   2,
   3
};

... müssen Sie das Komma an die bestehende Zeile anfügen und eine neue Zeile hinzufügen. Vergleichen Sie dies mit dem Fall, dass die drei bereits hat ein Komma hinter sich, wo Sie einfach eine Zeile hinzufügen müssen. Wenn Sie eine Zeile entfernen möchten, können Sie dies ebenfalls tun, ohne sich Gedanken darüber zu machen, ob es die letzte Zeile ist oder nicht, und Sie können Zeilen neu anordnen, ohne mit Kommas herumspielen zu müssen. Im Grunde bedeutet dies, dass die Zeilen einheitlich behandelt werden.

Denken Sie jetzt an die Codegenerierung. Etwas wie (Pseudocode):

output("int a[] = {");
for (int i = 0; i < items.length; i++) {
    output("%s, ", items[i]);
}
output("};");

Sie brauchen sich keine Gedanken darüber zu machen, ob der aktuelle Eintrag der erste oder der letzte ist, den Sie schreiben. Das ist viel einfacher.

132voto

Skilldrick Punkte 66961

Es ist nützlich, wenn Sie so etwas tun:

int a[] = {
  1,
  2,
  3, //You can delete this line and it's still valid
};

37voto

vcsjones Punkte 134300

Ich denke, dass es für den Entwickler einfach ist.

int a[] = {
            1,
            2,
            2,
            2,
            2,
            2, /*line I could comment out easily without having to remove the previous comma*/
          }

Und wenn Sie aus irgendeinem Grund ein Werkzeug haben, das den Code für Sie generiert, muss sich das Werkzeug nicht darum kümmern, ob es das letzte Element in der Initialisierung ist oder nicht.

31voto

Oliver Charlesworth Punkte 259497

Ich bin immer davon ausgegangen, dass es dadurch einfacher wird, zusätzliche Elemente anzuhängen:

int a[] = {
            5,
            6,
          };

wird einfach:

int a[] = { 
            5,
            6,
            7,
          };

zu einem späteren Zeitpunkt.

28voto

Shafik Yaghmour Punkte 147749

Ich bin überrascht, dass nach all dieser Zeit noch niemand die Annotiertes C++ Referenzhandbuch ( ARM ), steht folgendes über [dcl.init] Hervorhebung von mir:

Es gibt eindeutig zu viele Notationen für Initialisierungen, aber jede scheint für eine bestimmte Art der Verwendung gut geeignet zu sein. En \={initializer_list,opt} Notation wurde von C geerbt und eignet sich gut für die Initialisierung von Datenstrukturen und Arrays. [...]

obwohl sich die Grammatik seither weiterentwickelt hat ARM geschrieben wurde, bleibt der Ursprung erhalten.

und wir können zum C99 Begründung um zu sehen, warum dies in C erlaubt war, und da steht:

K&R erlaubt ein nachgestelltes Komma in einem Initialisierer am Ende einer Initialisierer-Liste. Der Standard hat diese Syntax beibehalten, s bietet Flexibilität beim Hinzufügen oder Löschen von Mitgliedern aus Liste und vereinfacht die maschinelle Erstellung solcher Listen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X