int a [] = {1,2,}; Seltsames Komma erlaubt. Irgend ein bestimmter Grund?

334

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.

Geben Sie hier die Bildbeschreibung ein

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?

Armen Tsirunyan
quelle
10
Jeder scheint damit einverstanden zu sein, dass es einfach ist, neue Zeilen hinzuzufügen - aber kümmern sich Leute , die Sprachspezifikationen definieren, wirklich um solche Dinge? Wenn sie wirklich so verständnisvoll sind, warum ignorieren sie dann nicht ein fehlendes, ;wenn klar ist, dass das nächste Token tatsächlich eine nächste Aussage ist?
YetAnotherUser
35
@YetAnotherUser: Ja, Sprachdesigner berücksichtigen solche Dinge. Das Löschen von Semikolons hätte eine viel größere Auswirkung und wäre in vielen Teilen der Sprache sehr vieldeutig (denken Sie daran, dass Leerzeichen in C nicht semantisch sind). Ein zusätzliches Komma ist in diesem Fall nicht mehrdeutig. Ein zusätzliches Semikolon ist fast nie mehrdeutig und daher auch zulässig. In dem Fall, in dem es mehrdeutig ist ( for()zum Beispiel nach a ), wird durch Hinzufügen eine Compiler-Warnung ausgegeben.
Rob Napier
5
@Tomalak: Es ist für einen menschlichen Leser mehrdeutig und oft ein Fehler. Deshalb gibt es eine Warnung. Ähnlich if (x = 1)ist es in der Grammatik nicht mehrdeutig, aber es ist für Menschen sehr mehrdeutig und wirft daher eine Warnung aus.
Rob Napier
12
@Rob: Dein ifBeispiel ist auch nicht mehrdeutig. Ich denke nicht, dass "mehrdeutig" bedeutet, was Sie denken, dass es bedeutet!
Leichtigkeitsrennen im Orbit
5
Solange wir uns einig sind, dass es für den Compiler nützlich ist, uns zu schützen, während ein nachfolgendes Komma in einer Array-Deklaration für den Compiler nicht nützlich ist, um uns davor zu schützen.
Rob Napier

Antworten:

435

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:

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

... 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):

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

Sie müssen sich keine Sorgen machen, ob der aktuelle Artikel, den Sie schreiben, der erste oder der letzte ist. Viel einfacher.

Jon Skeet
quelle
89
Bei Verwendung eines VCS ist der "Unterschied" zwischen zwei Versionen sauberer, da sich nur eine Zeile ändert, wenn ein Element hinzugefügt oder entfernt wird.
Kevin Panko
47
@ Néstor: Warum "unglücklich"? Was ist der Nachteil hier? Nur weil die Codegenerierung (und die einfache Manipulation) für einen winzigen Teil der Sprache in Betracht gezogen wurde, bedeutet dies nicht, dass dies die Hauptmotivation für alle Entscheidungen in der Sprache sein muss. Typinferenz, Entfernen von Semikolons usw. haben enorme Auswirkungen auf die Sprache. Sie stellen hier eine falsche Zweiteilung auf, IMO.
Jon Skeet
18
@ Néstor: Das ist , wo Pragmatismus Siegen gegen Dogmatismus: warum es sein muss vollständig eine Sache oder vollständig die andere, wenn es mehr sinnvoll eine Mischung aus beidem sein? Wie kommt es eigentlich in die Quere, am Ende ein Komma einfügen zu können? Ist dies eine Inkonsistenz, die Sie jemals in irgendeiner Weise behindert hat? Wenn nicht, wägen Sie diese irrelevante Uneleganz bitte gegen die praktischen Vorteile ab, wenn Sie am Ende ein Komma zulassen .
Jon Skeet
8
@ Mrchief: Es geht nicht um die Tippgeschwindigkeit, sondern um die Einfachheit beim Kopieren, Entfernen oder Neuanordnen von Elementen. Es hat mein Leben erst gestern einfacher gemacht. Warum nicht das Leben leichter machen, ohne Nachteile ? Was den Versuch betrifft, mit dem Finger auf MS zu zeigen, vermute ich stark, dass dies in C war, bevor es Microsoft überhaupt gab ... Sie sagen, diese Rechtfertigung scheint seltsam, aber ich wette, sie kommt jeden Tag Tausenden von Entwicklern in Hunderten von Unternehmen zugute. Ist das nicht eine bessere Erklärung, als nach etwas zu suchen, das Compiler-Autoren zugute kommt?
Jon Skeet
6
Dies war in K & R C.
Ferruccio
126

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

int a[] = {
  1,
  2,
  3, //You can delete this line and it's still valid
};
Skilldrick
quelle
6
JavaScript unterstützt diese Syntax: var a = [1, 2,];ebenso wie die meisten anderen Sprachen, die ich kenne ... ActionScript, Python, PHP.
Sean Fujiwara
14
@ Sean Das wird einen Analysefehler in IE JavaScript verursachen, also Vorsicht!
Skilldrick
10
In IE9 ist das nicht für mich. Aber es macht etwas Seltsames ... es erzeugt ein Nullelement. Ich werde aufpassen.
Sean Fujiwara
5
@ Sean Entschuldigung, Sie haben Recht - es ist kein Analysefehler im IE, aber es wird ein zusätzliches Element eingefügt, auf das gesetzt ist undefined.
Skilldrick
3
Am frustrierendsten ist, dass JSON diese Syntax nicht unterstützt.
Timmmm
38

Benutzerfreundlichkeit für den Entwickler, würde ich denken.

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

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.

vcsjones
quelle
32

Ich habe immer angenommen, dass es einfacher ist, zusätzliche Elemente anzuhängen:

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

wird einfach:

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

zu einem späteren Zeitpunkt.

Oliver Charlesworth
quelle
3
Ich denke nicht, dass eine etwas schnellere Bearbeitung ein guter Grund ist, die Syntax durcheinander zu bringen. IMHO ist dies nur eine weitere seltsame C ++ - Funktion.
Giorgio
3
@Giorgio: Nun, es ist von C geerbt. Es ist durchaus möglich, dass es nur ein Versehen in der ursprünglichen Sprachspezifikation ist, das zufällig einen nützlichen Nebeneffekt hat.
Oliver Charlesworth
Ok, ich wusste nicht, dass es von C kommt. Ich habe nur überprüft, ob es auch in Java erlaubt ist. Es fühlt sich allerdings irgendwie komisch an: In meiner Intuition ist das Komma ein Trennzeichen, kein Terminator. Außerdem kann das letzte Komma weggelassen werden. Also, ist es ein Terminator, ein Separator oder beides? Aber OK, diese Funktion ist verfügbar und es ist gut zu wissen.
Giorgio
11
@Giorgio - Quellcode ist für Menschen, nicht für Maschinen. Kleinigkeiten wie diese, die uns davon abhalten, einfache Umsetzungsfehler zu machen, sind ein Segen, kein Versehen. Als Referenz funktioniert es auch in PHP und ECMAScript (und damit in JavaScript und ActionScript) auf diese Weise, obwohl es in der JavaScript-Objektnotation (JSON) ungültig ist (z. B. [1,2,3,]OK, aber {a:1, b:2, c:3,}nicht).
Veröffentlicht
1
@Groky: Je mehr ich darüber nachdenke, desto mehr bin ich davon überzeugt, dass die Syntax einer Programmiersprache so einfach und konsistent wie möglich und mit so wenigen Ausnahmen wie möglich sein sollte: Dies erleichtert das Erlernen der Sprache (weniger Regeln, an die man sich erinnern muss) ). Der Vorteil, ein oder zwei Tastenanschläge beim Hinzufügen / Entfernen eines Elements zu / von einer Liste zu speichern (was ich übrigens nicht so oft mache, verglichen mit der Gesamtzeit, die ich mit dem Codieren verbringe), erscheint mir im Vergleich zu eher trivial mit einer klar definierten Syntax.
Giorgio
21

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:

int ints[] = {
    3,
    9
};

Angenommen, Sie haben diesen Code in ein Repository eingecheckt.

Dann bearbeitet Ihr Kumpel es und fügt am Ende hinzu:

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

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

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

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.

amoss
quelle
15

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

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

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.

Gene Bushuyev
quelle
5
Ich bin völlig anderer Meinung; [Ich bin der Meinung, dass] es seinen Weg in viele Sprachen gefunden hat, die lange nach C erstellt wurden, gerade weil es für den Programmierer von Vorteil ist, den Inhalt des Arrays verschieben, Zeilen wohl oder übel auskommentieren zu können und so weiter. ohne sich um dumme transpositionsbedingte Syntaxfehler sorgen zu müssen. Sind wir nicht schon genug gestresst?
Veröffentlicht
12
@Dereleased - nach der gleichen Logik, warum sollte das Nachlaufen (irgendetwas) nicht erlaubt sein, wie wäre es int a = b + c +;oder if(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.
Gene Bushuyev
1
@ Gene Bushuyev: Genau! Ich habe oft lange Ausdrücke mit + oder &&, mit dem Operator am Ende der Zeile, und natürlich muss ich etwas mehr Zeit aufwenden, wenn ich den letzten Operanden des Ausdrucks entfernen möchte. Ich finde diese Kommasyntax wirklich seltsam!
Giorgio
2
@GeneBushuyev - da bin ich anderer Meinung. Das Zulassen von nachgestellten Kommas in Arrays und dergleichen ist eine Funktion zur Fehlerbehebung und erleichtert Ihnen das Leben als Programmierer. Aus Gründen der Lesbarkeit würde ich jedoch Maßnahmen ergreifen, um nachfolgende AND (&&) -Anweisungen, Plusses und andere verschiedene Operatoren aus der Bedingung zu entfernen Aussagen. Es ist einfach nur hässlich, IMO.
Sune Rasmussen
2
In Bezug auf den &&Operator mache ich manchmal Bedingungen wie diese, if (true \n && b1 \n && b2)damit ich nach Bedarf Zeilen hinzufügen und entfernen kann.
Christian Mann
12

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.

Fredrik Pihl
quelle
11

Dies erleichtert Codegeneratoren, die Arrays oder Aufzählungen ausspucken.

Vorstellen:

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

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:

print("enum Items {")
print(",\n".join(items))
print("}")
Maxim Egorushkin
quelle
10

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:

Es gibt eindeutig zu viele Notationen für Initialisierungen, aber jede scheint einem bestimmten Verwendungsstil gut zu dienen. Die Notation = {initializer_list, opt} wurde von C geerbt und dient gut zur Initialisierung von Datenstrukturen und Arrays. [...]

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:

K & R erlaubt ein nachfolgendes Komma in einem Initialisierer am Ende einer Initialisiererliste. Der Standard hat diese Syntax beibehalten, da er Flexibilität beim Hinzufügen oder Löschen von Elementen zu einer Initialisierungsliste bietet und die maschinelle Generierung solcher Listen vereinfacht.

Shafik Yaghmour
quelle
1
Upvote für die am besten unterstützte Antwort in der Literatur und die wahre Quelle dieser Funktion.
Marko
10

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

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

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.

Ruckelt
quelle
7

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

Thomas Bonini
quelle
Die "Arrays" von JavaScript (die nur Objekte mit einer magischen Längeneigenschaft sind) sind sowieso eher ungewöhnlich: var x = [,,,]sind legal (außer in IE <9, aber die Spezifikation sagt, dass sie legal sind)
Peter C
Gemäß der ECMAScript-Spezifikation ist es vollkommen gültig; Theoretisch sollte es in jedem Browser funktionieren, der JavaScript gemäß der genannten Spezifikation implementiert, insbesondere in dem Teil der hier enthaltenen Spezifikation .
Veröffentlicht
1
Leider geht es bei JavaScript nur darum, Apps für die Öffentlichkeit zu erstellen. Nein, es ist nicht vollständig gültig, wenn ~ 50% der Benutzer Probleme mit der Verwendung Ihrer App haben würden. Und ja, wenn ich könnte, würde ich IE <9 verbieten - einfach zu viel Stunden damit verbringen, guten Code dort zu
erstellen
@Dere: Ja, das habe ich in meiner Antwort gesagt =)
Thomas Bonini
@Dereleased Microsoft erfindet seine eigenen Spezifikationen und Befehle, dass andere zumindest daran festhalten, dass sich die Mentalität ändert (Gott sei Dank)
Chris McGrath
7

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?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    puts("Line 1");
    puts("Line 2");
    puts("Line 3");

    return EXIT_SUCCESS
}

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?

Louis
quelle
Es gibt Sprachen (zB Pascal), die das zulassen. Dh du musst wählen zwischen; als Terminator (C) oder als Separator (Pascal). Gleiches gilt für ','. Es wäre für mich in Ordnung, wenn ',' ein Terminator ist, aber dann muss {1, 2, 3} ein Syntaxfehler sein.
Giorgio
6

Der Grund ist trivial: Einfaches Hinzufügen / Entfernen von Zeilen.

Stellen Sie sich den folgenden Code vor:

int a[] = {
   1,
   2,
   //3, // - not needed any more
};

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.

Vlad
quelle
6

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.

Mark B.
quelle
5

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.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Super User",
        "Server Fault"
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Und es ist großartig, da es die ursprüngliche Trilogie der Stack Exchange-Sites zeigt.

Stack Overflow
Super User
Server Fault

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.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Server Fault"
        "Super User",
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Das Bewegen von Linien könnte doch nicht so schwer sein, oder?

Stack Overflow
Server FaultSuper User

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 .

Konrad Borowski
quelle
4

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":

char *available_resources[] = {
"color monitor"           ,
"big disk"                ,
"Cray"                      /* whoa! no comma! */
"on-line drawing routines",
"mouse"                   ,
"keyboard"                ,
"power cables"            , /* and what's this extra comma? */
};

wir lesen :

... dass das nachfolgende Komma nach dem endgültigen Initialisierer kein Tippfehler ist, sondern ein Fehler in der Syntax, der von Aboriginal C übernommen wurde . Seine Anwesenheit oder Abwesenheit ist erlaubt, hat aber keine Bedeutung . Die in der ANSI C-Begründung geltend gemachte Rechtfertigung besteht darin, dass dies die automatisierte Erzeugung von C erleichtert. Die Behauptung wäre glaubwürdiger, wenn in jeder durch Kommas getrennten Liste nachgestellte Kommas zulässig wären , z. B. in Aufzählungsdeklarationen oder in mehreren Deklaratoren mit mehreren Variablen in einer einzigen Deklaration. Sie sind nicht.

... für mich macht das mehr Sinn

Nikos Athanasiou
quelle
2
Das Verbot des Kommas in diesem enumFall ist etwas interessant, da das fehlende Komma die geringste Mehrdeutigkeit darstellen würde. Gegeben struct 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 ...
Supercat
1
... da C bereit ist, das Komma in einem Fall zu ignorieren, in dem ihm vernünftigerweise eine signifikante Bedeutung hätte zugewiesen werden können (aber nicht) (was ein starkes Argument dafür wäre, es dort zu verbieten), ist es merkwürdig, dass dies nicht der Fall ist Nicht bereit in einem Fall, in dem das Komma keine Bedeutung haben könnte [selbst wenn man das enum foo {moe,,larry,curly,};Überspringen einer Zahl zwischen moeund interpretiert larry, 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 ...
Supercat
1
... könnte einfach dadurch behandelt werden, dass ein Überlauf, der nach dem zuletzt zugewiesenen Aufzählungswert auftritt, ignoriert werden sollte.
Supercat
@supercat Es gibt Sprachen wie C #, in denen A-priori-Designforschung so weit geht, IDE-Funktionen und -Integration bei der Entwicklung der Sprache zu berücksichtigen. C war (und konnte nicht) eine dieser Sprachen.
Nikos Athanasiou
Selbst bei Sprachen wie C # haben sich ändernde Designziele zu ziemlich schwerwiegenden Designinkonsistenzen geführt. Zum Beispiel verzichtete die Sprache darauf, irgendeine Form der Überladung vom Rückgabetyp für normale Methoden und Operatoren zu unterstützen (obwohl das zugrunde liegende Framework dies unterstützen könnte), da dies als dem Ziel einer einfach zu kompilierenden Sprache entgegengesetzt angesehen wurde Die Lambda-Bewertung umfasst Typinferenzregeln, deren Auflösung NP-vollständig ist. Das Hinzufügen neuer Methoden- / Operator-Überladungsregeln könnte den vorhandenen Code
beschädigen
2

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 enumDefinition.

Iravanchi
quelle
1

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:

#define LIST_BEGIN int a[] = {
#define LIST_ENTRY(x) x,
#define LIST_END };

Verwendungszweck:

LIST_BEGIN
   LIST_ENTRY(1)
   LIST_ENTRY(2)
LIST_END

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:

#define LIST_LAST_ENTRY(x) x

und das wäre sehr umständlich zu bedienen.

Scott Langham
quelle
0

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.

noɥʇʎԀʎzɐɹƆ
quelle
-4

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

zhi_jian
quelle
Ist dies ein Fehler für VC6, der nicht dem Standard entspricht?
Thomson