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?

21voto

amoss Punkte 1561

Alles, was alle über die Leichtigkeit des Hinzufügens/Entfernens/Generierens von Zeilen sagen, ist richtig, aber der eigentliche Vorteil dieser Syntax liegt im Zusammenführen von Quelldateien. Stellen Sie sich vor, Sie haben dieses Array:

int ints[] = {
    3,
    9
};

Und gehen Sie davon aus, dass Sie diesen Code in ein Repository eingecheckt haben.

Dann bearbeitet dein Kumpel den Text und fügt das Ende hinzu:

int ints[] = {
    3,
    9,
    12
};

Und gleichzeitig bearbeiten Sie es und fügen den Anfang hinzu:

int ints[] = {
    1,
    3,
    9
};

Semantisch gesehen sollten diese Art von Operationen (Hinzufügen am Anfang, Hinzufügen am Ende) völlig sicher sein und Ihre Versionierungssoftware (hoffentlich Git) sollte in der Lage sein, die Zusammenführung zu automatisieren. Leider ist das nicht der Fall, weil Ihre Version kein Komma nach der 9 hat, die Ihres Freundes aber schon. Hätte die ursprüngliche Version jedoch die nachgestellte 9, hätten sie automatisch zusammengeführt.

Meine Faustregel lautet also: Verwenden Sie das nachgestellte Komma, wenn sich die Liste über mehrere Zeilen erstreckt, und lassen Sie es weg, wenn die Liste in einer einzigen Zeile steht.

15voto

Yankes Punkte 1712

Ich sehe einen Anwendungsfall, der in anderen Antworten nicht erwähnt wurde, unsere bevorzugten Makros:

int a [] = {
#ifdef A
    1, //this can be last if B and C is undefined
#endif
#ifdef B
    2,
#endif
#ifdef C
    3,
#endif
};

Hinzufügen von Makros zur Handhabung der letzten , wäre ein großer Schmerz. Mit dieser kleinen Änderung der Syntax ist dies trivial zu handhaben. Und das ist wichtiger als maschinengenerierter Code, weil es normalerweise viel einfacher ist, dies in einer vollständigen Turing-Sprache zu tun als in einem sehr begrenzten Präprozessor.

15voto

Gene Bushuyev Punkte 5424

Das Komma am Ende ist meines Erachtens aus Gründen der Abwärtskompatibilität zulässig. Es gibt eine Menge bestehenden Code, vor allem automatisch generierten, der ein Komma am Ende setzt. Es macht es einfacher, eine Schleife ohne spezielle Bedingung am Ende zu schreiben. z.B..

for_each(my_inits.begin(), my_inits.end(),
[](const std::string& value) { std::cout << value << ",\n"; });

Es gibt keinen wirklichen Vorteil für den Programmierer.

P.S. Obwohl es einfacher ist, den Code auf diese Weise automatisch zu generieren, habe ich eigentlich immer darauf geachtet, das nachgestellte Komma nicht zu setzen, der Aufwand ist minimal, die Lesbarkeit wird verbessert, und das ist wichtiger. Man schreibt den Code einmal, man liest ihn viele Male.

13voto

Fredrik Pihl Punkte 42950

Einer der Gründe, warum dies erlaubt ist, ist meines Wissens, dass es einfach sein sollte, automatisch Code zu generieren; Sie brauchen keine besondere Behandlung für das letzte Element.

12voto

Maxim Egorushkin Punkte 125210

Es macht Code-Generatoren, die Arrays oder Aufzählungen ausspucken, einfacher.

Stellen Sie sich vor:

std::cout << "enum Items {\n";
for(Items::iterator i(items.begin()), j(items.end); i != j; ++i)
    std::cout << *i << ",\n";
std::cout << "};\n";

D.h., es ist nicht notwendig, das erste oder letzte Element besonders zu behandeln, um zu vermeiden, dass das nachgestellte Komma verschoben wird.

Wenn der Codegenerator beispielsweise in Python geschrieben ist, kann man das Komma am Ende leicht vermeiden, indem man str.join() Funktion:

print("enum Items {")
print(",\n".join(items))
print("}")

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