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
Aber es ist nicht. Ich war überrascht, als dieser Code in Visual Studio kompiliert wurde, aber ich habe gelernt, dem MSVC-Compiler in Bezug auf C ++ - Regeln nicht zu vertrauen. Deshalb habe ich den Standard überprüft und er ist auch nach dem Standard zulässig. Sie können 8.5.1 für die Grammatikregeln sehen, wenn Sie mir nicht glauben.
Warum ist das erlaubt? Dies mag eine dumme, nutzlose Frage sein, aber ich möchte, dass Sie verstehen, warum ich frage. Wenn es ein Unterfall einer allgemeinen Grammatikregel wäre, würde ich verstehen - sie haben beschlossen, die allgemeine Grammatik nicht schwieriger zu machen, nur um ein redundantes Komma am Ende einer Initialisiererliste zu verbieten. Aber nein, das zusätzliche Komma ist ausdrücklich erlaubt. Beispielsweise darf am Ende einer Funktionsaufruf-Argumentliste (wenn die Funktion ausgeführt wird ...
) kein redundantes Komma stehen , was normal ist .
Gibt es also wieder einen bestimmten Grund, warum dieses redundante Komma ausdrücklich zulässig ist?
quelle
;
wenn klar ist, dass das nächste Token tatsächlich eine nächste Aussage ist?for()
zum Beispiel nach a ), wird durch Hinzufügen eine Compiler-Warnung ausgegeben.if (x = 1)
ist es in der Grammatik nicht mehrdeutig, aber es ist für Menschen sehr mehrdeutig und wirft daher eine Warnung aus.if
Beispiel ist auch nicht mehrdeutig. Ich denke nicht, dass "mehrdeutig" bedeutet, was Sie denken, dass es bedeutet!Antworten:
Es erleichtert das Generieren von Quellcode und das Schreiben von Code, der zu einem späteren Zeitpunkt problemlos erweitert werden kann. Überlegen Sie, was erforderlich ist, um einen zusätzlichen Eintrag hinzuzufügen:
... müssen Sie das Komma zur vorhandenen Zeile hinzufügen und eine neue Zeile hinzufügen. Vergleichen Sie das mit dem Fall, in dem die drei bereits ein Komma hinter sich haben und Sie nur eine Zeile hinzufügen müssen. Wenn Sie eine Zeile entfernen möchten, können Sie dies auch tun, ohne sich Gedanken darüber zu machen, ob es sich um die letzte Zeile handelt oder nicht, und Sie können Zeilen neu anordnen, ohne mit Kommas herumzuspielen. Grundsätzlich bedeutet dies, dass die Behandlung der Linien einheitlich ist.
Denken Sie jetzt daran, Code zu generieren. So etwas wie (Pseudocode):
Sie müssen sich keine Sorgen machen, ob der aktuelle Artikel, den Sie schreiben, der erste oder der letzte ist. Viel einfacher.
quelle
Es ist nützlich, wenn Sie so etwas tun:
quelle
var a = [1, 2,];
ebenso wie die meisten anderen Sprachen, die ich kenne ... ActionScript, Python, PHP.undefined
.Benutzerfreundlichkeit für den Entwickler, würde ich denken.
Wenn Sie aus irgendeinem Grund ein Tool hatten, das Code für Sie generiert hat; Das Tool muss sich nicht darum kümmern, ob es das letzte Element in der Initialisierung ist oder nicht.
quelle
Ich habe immer angenommen, dass es einfacher ist, zusätzliche Elemente anzuhängen:
wird einfach:
zu einem späteren Zeitpunkt.
quelle
[1,2,3,]
OK, aber{a:1, b:2, c:3,}
nicht).Alles, was alle über das einfache Hinzufügen / Entfernen / Generieren von Zeilen sagen, ist korrekt, aber der eigentliche Ort, an dem diese Syntax leuchtet, ist das Zusammenführen von Quelldateien. Stellen Sie sich vor, Sie haben dieses Array:
Angenommen, Sie haben diesen Code in ein Repository eingecheckt.
Dann bearbeitet Ihr Kumpel es und fügt am Ende hinzu:
Und Sie bearbeiten es gleichzeitig und fügen am Anfang hinzu:
Semantisch sollten diese Arten von Vorgängen (Hinzufügen am Anfang, Hinzufügen am Ende) vollständig zusammenführungssicher sein und Ihre Versionierungssoftware (hoffentlich git) sollte in der Lage sein, automatisiert zu werden. Leider ist dies nicht der Fall, da Ihre Version nach der 9 kein Komma hat und Ihr Freund dies tut. Wenn die ursprüngliche Version die nachfolgende 9 hätte, wären sie automatisch zusammengeführt worden.
Meine Faustregel lautet also: Verwenden Sie das nachfolgende Komma, wenn die Liste mehrere Zeilen umfasst. Verwenden Sie es nicht, wenn sich die Liste in einer einzelnen Zeile befindet.
quelle
Nachfolgendes Komma ist meines Erachtens aus Gründen der Abwärtskompatibilität zulässig. Es gibt viel vorhandenen Code, der hauptsächlich automatisch generiert wird und ein nachfolgendes Komma enthält. Es erleichtert das Schreiben einer Schleife ohne besondere Bedingung am Ende. z.B
Für den Programmierer gibt es keinen wirklichen Vorteil.
PS Obwohl es einfacher ist, den Code auf diese Weise automatisch zu generieren, habe ich eigentlich immer darauf geachtet, das nachfolgende Komma nicht zu setzen. Der Aufwand ist minimal, die Lesbarkeit wird verbessert, und das ist wichtiger. Sie schreiben Code einmal, Sie lesen ihn oft.
quelle
int a = b + c +;
oderif(a && b &&);
es wird einfacher sein, am Ende einfach etwas zu kopieren und einzufügen und Codegeneratoren einfacher zu schreiben. Dieses Problem ist sowohl trivial als auch subjektiv. In solchen Fällen ist es immer gut, das zu tun, was für den Codeleser am besten ist.&&
Operator mache ich manchmal Bedingungen wie diese,if (true \n && b1 \n && b2)
damit ich nach Bedarf Zeilen hinzufügen und entfernen kann.Einer der Gründe, warum dies meines Wissens zulässig ist, ist, dass es einfach sein sollte, automatisch Code zu generieren. Für das letzte Element benötigen Sie keine spezielle Behandlung.
quelle
Dies erleichtert Codegeneratoren, die Arrays oder Aufzählungen ausspucken.
Vorstellen:
Das heißt, es ist nicht erforderlich, das erste oder letzte Element speziell zu behandeln, um ein spuckendes Komma zu vermeiden.
Wenn der Codegenerator beispielsweise in Python geschrieben ist, können Sie das folgende Komma leicht vermeiden, indem Sie die folgenden
str.join()
Funktionen verwenden:quelle
Ich bin überrascht, dass nach all dieser Zeit niemand das Annotated C ++ Reference Manual ( ARM ) zitiert hat. Es sagt Folgendes über [dcl.init] mit Schwerpunkt auf meinem:
Obwohl sich die Grammatik seit dem Schreiben von ARM weiterentwickelt hat , bleibt der Ursprung erhalten.
und wir können zur C99-Begründung gehen, um zu sehen, warum dies in C erlaubt war und es heißt:
quelle
Ich sehe einen Anwendungsfall, der in anderen Antworten nicht erwähnt wurde, unsere Lieblingsmakros:
Das Hinzufügen von Makros zum letzten Mal
,
wäre ein großer Schmerz. Mit dieser kleinen Änderung der Syntax ist dies trivial zu verwalten. Und dies ist wichtiger als maschinengenerierter Code, da dies in der vollständigen Sprache von Turing normalerweise viel einfacher ist als ein sehr begrenzter Präprozessor.quelle
Die einzige Sprache, in der es - in der Praxis * - nicht erlaubt ist, ist Javascript, und es verursacht unzählige Probleme. Wenn Sie beispielsweise eine Zeile aus der Mitte des Arrays kopieren und einfügen, am Ende einfügen und vergessen haben, das Komma zu entfernen, ist Ihre Site für Ihre IE-Besucher völlig fehlerhaft.
* Theoretisch ist dies zulässig, aber der Internet Explorer folgt nicht dem Standard und behandelt ihn als Fehler
quelle
var x = [,,,]
sind legal (außer in IE <9, aber die Spezifikation sagt, dass sie legal sind)Es ist einfacher für Maschinen, dh das Parsen und Generieren von Code. Es ist auch einfacher für den Menschen, dh Modifikation, Auskommentieren und visuelle Eleganz durch Konsistenz.
Angenommen, C, würden Sie Folgendes schreiben?
Nein, nicht nur, weil die endgültige Aussage ein Fehler ist, sondern auch, weil sie inkonsistent ist. Warum also das Gleiche mit Sammlungen tun? Selbst in Sprachen, in denen Sie die letzten Semikolons und Kommas weglassen können, mag es die Community normalerweise nicht. Die Perl-Community zum Beispiel scheint es nicht zu mögen, Semikolons wegzulassen, außer Einzeiler. Sie wenden das auch auf Kommas an.
Lassen Sie Kommas in mehrzeiligen Sammlungen nicht aus demselben Grund weg, aus dem Sie keine Semikolons für mehrzeilige Codeblöcke auslassen. Ich meine, du würdest es nicht tun, selbst wenn die Sprache es zulässt, oder? Recht?
quelle
Der Grund ist trivial: Einfaches Hinzufügen / Entfernen von Zeilen.
Stellen Sie sich den folgenden Code vor:
Jetzt können Sie der Liste problemlos Elemente hinzufügen / entfernen, ohne manchmal das nachfolgende Komma hinzufügen / entfernen zu müssen.
Im Gegensatz zu anderen Antworten denke ich nicht, dass die einfache Erstellung der Liste ein triftiger Grund ist: Schließlich ist es für den Code trivial, die letzte (oder erste) Zeile als Sonderfall zu verwenden. Codegeneratoren werden einmal geschrieben und oft verwendet.
quelle
Es ermöglicht jeder Zeile, der gleichen Form zu folgen. Erstens erleichtert dies das Hinzufügen neuer Zeilen und lässt ein Versionskontrollsystem die Änderung sinnvoll verfolgen, und ermöglicht es Ihnen, den Code einfacher zu analysieren. Ich kann mir keinen technischen Grund vorstellen.
quelle
Dies ist vor Fehlern geschützt, die durch das Verschieben von Elementen in einer langen Liste verursacht werden.
Nehmen wir zum Beispiel an, wir haben einen Code, der so aussieht.
Und es ist großartig, da es die ursprüngliche Trilogie der Stack Exchange-Sites zeigt.
Aber es gibt ein Problem damit. Sie sehen, die Fußzeile auf dieser Website zeigt Serverfehler vor Superuser. Beheben Sie das besser, bevor es jemand bemerkt.
Das Bewegen von Linien könnte doch nicht so schwer sein, oder?
Ich weiß, es gibt keine Website namens "Server FaultSuper User", aber unser Compiler behauptet, dass sie existiert. Das Problem ist nun, dass C über eine Funktion zur Verkettung von Zeichenfolgen verfügt, mit der Sie zwei Zeichenfolgen in doppelten Anführungszeichen schreiben und sie mit nichts verketten können (ein ähnliches Problem kann auch bei Ganzzahlen auftreten, z
-
Vorzeichen mehrere Bedeutungen hat).Was wäre, wenn das ursprüngliche Array am Ende ein nutzloses Komma hätte? Nun, die Linien würden verschoben, aber ein solcher Fehler wäre nicht aufgetreten. Es ist leicht, etwas so Kleines wie ein Komma zu übersehen. Wenn Sie daran denken, nach jedem Array-Element ein Komma zu setzen, kann ein solcher Fehler einfach nicht auftreten. Sie möchten nicht vier Stunden damit verschwenden, etwas zu debuggen, bis Sie feststellen, dass das Komma die Ursache für Ihre Probleme ist .
quelle
Wie viele andere Dinge ist das nachfolgende Komma in einem Array-Initialisierer eines der Dinge, die C ++ von C geerbt hat (und für immer unterstützen muss). Eine völlig andere Ansicht als die hier platzierte wird im Buch "Deep C Secrets" erwähnt. .
Darin nach einem Beispiel mit mehr als einem "Komma-Paradoxon":
wir lesen :
... für mich macht das mehr Sinn
quelle
enum
Fall ist etwas interessant, da das fehlende Komma die geringste Mehrdeutigkeit darstellen würde. Gegebenstruct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }
; Es gibt zwei sinnvolle Bedeutungen, die die Sprache zuweisen könnte: Erstellen Sie ein Array mit zwei Elementen oder erstellen Sie ein Array mit drei Elementen, in dem das letzte Element Standardwerte hat. Wenn C die spätere Interpretation übernommen hätte, könnte ich das Verbot verbieten,enum foo {moe, larry, curly, };
dass es nur einen Weg geben sollte, die Aussage zu schreiben (ohne Komma), aber ...enum foo {moe,,larry,curly,};
Überspringen einer Zahl zwischenmoe
und interpretiertlarry
, spielt es im Allgemeinen keine Rolle, ob das nachfolgende Komma verarbeitet oder ignoriert wird. Der einzige Fall, in dem es wichtig sein könnte, wäre, wenn das letzte Element der Maximalwert für seinen deklarierten Typ wäre und dass ...Wenn Sie einen Parser implementieren möchten, ist diese Art der Grammatik nicht nur einfacher zu generieren und zu bearbeiten, sondern auch einfacher und einfacher zu implementieren. C # folgt dieser Regel an mehreren Stellen, dass es eine Liste von durch Kommas getrennten Elementen gibt, wie z. B. Elemente in einer
enum
Definition.quelle
Dies erleichtert das Generieren von Code, da Sie nur eine Zeile hinzufügen müssen und das Hinzufügen des letzten Eintrags nicht so behandeln müssen, als wäre es ein Sonderfall. Dies gilt insbesondere dann, wenn Makros zum Generieren von Code verwendet werden. Es wird versucht zu versuchen, die Notwendigkeit von Makros aus der Sprache zu entfernen, aber ein Großteil der Sprache hat sich Hand in Hand mit der Verfügbarkeit von Makros entwickelt. Mit dem zusätzlichen Komma können Makros wie die folgenden definiert und verwendet werden:
Verwendungszweck:
Das ist ein sehr vereinfachtes Beispiel, aber häufig wird dieses Muster von Makros verwendet, um Dinge wie Versand-, Nachrichten-, Ereignis- oder Übersetzungskarten und -tabellen zu definieren. Wenn am Ende kein Komma erlaubt wäre, bräuchten wir ein spezielles:
und das wäre sehr umständlich zu bedienen.
quelle
Wenn zwei Personen ein neues Element in einer Liste in separaten Zweigen hinzufügen, kann Git die Änderungen ordnungsgemäß zusammenführen, da Git zeilenweise arbeitet.
quelle
Wenn Sie ein Array ohne angegebene Länge verwenden, kann VC ++ 6.0 seine Länge automatisch identifizieren. Wenn Sie also "int a [] = {1,2,};" verwenden, beträgt die Länge von a 3, die letzte jedoch nicht. Wenn Sie nicht initialisiert wurden, können Sie "cout <" verwenden
quelle