int a [] = {1,2,}; Virgule étrange autorisée. N'importe quelle raison?

335

Je ne suis peut-être pas de cette planète, mais il me semble que ce qui suit devrait être une erreur de syntaxe:

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

Mais ce n'est pas. J'ai été surpris lorsque ce code a été compilé sur Visual Studio, mais j'ai appris à ne pas faire confiance au compilateur MSVC en ce qui concerne les règles C ++, j'ai donc vérifié la norme et elle est également autorisée par la norme. Vous pouvez voir 8.5.1 pour les règles de grammaire si vous ne me croyez pas.

entrez la description de l'image ici

Pourquoi est-ce autorisé? C'est peut-être une stupide question inutile, mais je veux que vous compreniez pourquoi je pose la question. S'il s'agissait d'un sous-cas d'une règle de grammaire générale, je comprendrais - ils ont décidé de ne pas rendre la grammaire générale plus difficile simplement pour interdire une virgule redondante à la fin d'une liste d'initialisation. Mais non, la virgule supplémentaire est explicitement autorisée. Par exemple, il n'est pas autorisé d'avoir une virgule redondante à la fin d'une liste d'arguments d'appel de fonction (lorsque la fonction prend ...), ce qui est normal .

Donc, encore une fois, y a-t-il une raison particulière pour laquelle cette virgule redondante est explicitement autorisée?

Armen Tsirunyan
la source
10
Tout le monde semble accepter «la facilité d'ajouter une nouvelle ligne» - mais les gens qui définissent les spécifications linguistiques se soucient-ils vraiment de telles choses? S'ils ont vraiment cette compréhension, alors pourquoi ne pas ignorer un manquant ;quand il est clair que le prochain jeton est en fait une prochaine déclaration.
YetAnotherUser
35
@YetAnotherUser: Oui, les concepteurs de langage considèrent de telles choses. Vous permettre de supprimer des points-virgules aurait un impact beaucoup plus important et serait très ambigu dans de nombreuses parties du langage (rappelez-vous que les espaces blancs ne sont pas sémantiques en C). Une virgule supplémentaire est que ce cas n'est pas ambigu. Un point-virgule supplémentaire n'est presque jamais ambigu et est donc également autorisé. Dans le cas où il est ambigu (après un for()par exemple), l'ajouter lève un avertissement du compilateur.
Rob Napier
5
@Tomalak: C'est ambigu pour un lecteur humain et c'est souvent une erreur. C'est pourquoi il lance un avertissement. De même if (x = 1)n'est pas ambigu dans la grammaire, mais il est très ambigu pour les humains, et lance donc un avertissement.
Rob Napier
12
@Rob: Votre ifexemple n'est pas ambigu non plus. Je ne pense pas que "ambigu" signifie ce que vous pensez que cela signifie!
Courses de légèreté en orbite
5
Tant que nous convenons qu'il est utile pour le compilateur de nous protéger, alors qu'une virgule de fin dans une déclaration de tableau n'est pas quelque chose d'utile pour le compilateur de nous protéger.
Rob Napier

Réponses:

436

Il facilite la génération de code source, ainsi que l'écriture de code qui peut être facilement étendu ultérieurement. Considérez ce qui est nécessaire pour ajouter une entrée supplémentaire à:

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

... vous devez ajouter la virgule à la ligne existante et ajouter une nouvelle ligne. Comparez cela avec le cas où les trois ont déjà une virgule après, où il vous suffit d'ajouter une ligne. De même, si vous souhaitez supprimer une ligne, vous pouvez le faire sans vous soucier de savoir s'il s'agit de la dernière ligne ou non, et vous pouvez réorganiser les lignes sans tripoter les virgules. Fondamentalement, cela signifie qu'il y a une uniformité dans la façon dont vous traitez les lignes.

Pensez maintenant à générer du code. Quelque chose comme (pseudo-code):

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

Pas besoin de vous soucier de savoir si l'élément actuel que vous écrivez est le premier ou le dernier. Beaucoup plus simple.

Jon Skeet
la source
89
De plus, lorsque vous utilisez un VCS, le "diff" entre deux versions est plus propre, car une seule ligne change lorsqu'un élément est ajouté ou supprimé.
Kevin Panko
47
@ Néstor: Pourquoi "malheureux"? Quel est l'inconvénient ici? Ce n'est pas parce qu'une certaine considération a été accordée à la génération de code (et à la manipulation aisée) pour une petite partie du langage qu'elle doit être la principale motivation derrière toutes les décisions dans le langage. L'inférence de type, la suppression des points-virgules, etc. ont d' énormes implications pour la langue. Vous créez une fausse dichotomie ici, OMI.
Jon Skeet
18
@ Néstor: C'est où le pragmatisme l' emporte sur le dogmatisme: pourquoi doit - il être complètement une chose ou bien l'autre, quand il est plus utile d'être un mélange des deux? Comment cela gêne-t-il réellement, en pouvant ajouter une virgule à la fin? Est-ce une incohérence qui vous a jamais gêné dans un sens? Sinon, veuillez peser cette inélégance non pertinente par rapport aux avantages pratiques de permettre une virgule à la fin.
Jon Skeet
8
@Mrchief: Ce n'est pas une question de taux de frappe - c'est une question de simplicité, lorsque vous copiez, supprimez ou réorganisez des éléments. Hier, cela m'a simplifié la vie. Sans inconvénient, pourquoi ne pas vous faciliter la vie? Quant à essayer de pointer du doigt MS, je soupçonne fortement que cela a été en C depuis avant même que Microsoft existe ... Vous dites que cette justification semble étrange, mais je parie qu'elle profite à des milliers de développeurs à travers des centaines d'entreprises chaque jour. N'est-ce pas une meilleure explication que de chercher quelque chose qui profite aux rédacteurs de compilateurs?
Jon Skeet
6
C'était dans K&R C.
Ferruccio
126

C'est utile si vous faites quelque chose comme ceci:

int a[] = {
  1,
  2,
  3, //You can delete this line and it's still valid
};
Skilldrick
la source
6
JavaScript prend en charge cette syntaxe var a = [1, 2,];:, tout comme la plupart des autres langages que je connais ... ActionScript, Python, PHP.
Sean Fujiwara
14
@Sean Cela provoquera une erreur d'analyse dans IE JavaScript, alors méfiez-vous!
Skilldrick
10
Ce n'est pas pour moi dans IE9. Mais cela fait quelque chose d'étrange ... cela crée un élément nul. Je me méfierai.
Sean Fujiwara
5
@Sean Désolé, vous avez raison - ce n'est pas une erreur d'analyse dans IE, mais il va insérer un ensemble d'élément supplémentaire à undefined.
Skilldrick
3
Plus frustrant encore, JSON ne prend pas en charge cette syntaxe.
Timmmm
38

Facilité d'utilisation pour le développeur, je pense.

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

De plus, si pour une raison quelconque, vous disposiez d'un outil qui générait du code pour vous; l'outil n'a pas à se soucier de savoir s'il s'agit du dernier élément de l'initialisation ou non.

vcsjones
la source
32

J'ai toujours supposé qu'il était plus facile d'ajouter des éléments supplémentaires:

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

devient simplement:

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

à une date ultérieure.

Oliver Charlesworth
la source
3
Je ne pense pas que rendre l'édition un peu plus rapide soit une bonne raison de gâcher la syntaxe. À mon humble avis, c'est juste une autre fonctionnalité C ++ étrange.
Giorgio
3
@Giorgio: Eh bien, il est hérité de C. Il est tout à fait possible que ce soit juste une erreur dans la spécification de la langue d'origine, qui se trouve avoir un effet secondaire utile.
Oliver Charlesworth
Ok, je ne savais pas que cela venait de C. Je viens de vérifier qu'il est également autorisé en Java. Cela semble un peu étrange cependant: dans mon intuition, la virgule est un séparateur et non un terminateur. De plus, il est possible d'omettre la dernière virgule. Alors, est-ce un terminateur, un séparateur ou les deux? Mais bon, cette fonctionnalité est disponible et c'est bon à savoir.
Giorgio
11
@Giorgio - le code source est pour les humains, pas pour les machines. De petites choses comme celle-ci pour nous empêcher de commettre de simples erreurs de transposition sont une bénédiction et non un oubli. Pour référence, il fonctionne également de cette façon en PHP et ECMAScript (et donc en JavaScript et ActionScript), bien qu'il ne soit pas valide en notation d'objet JavaScript (JSON) (par exemple, [1,2,3,]est OK mais {a:1, b:2, c:3,}ne l'est pas).
Sorti
1
@Groky: Plus j'y pense, plus je suis convaincu que la syntaxe d'un langage de programmation doit être aussi simple et cohérente que possible et avec le moins d'exceptions possible: cela facilite l'apprentissage du langage (moins de règles à retenir ). L'avantage de sauvegarder une ou deux touches lors de l'ajout / suppression d'un élément à / d'une liste (ce qui, soit dit en passant, je ne le fais pas souvent par rapport au temps total que je passe à coder) me semble plutôt trivial par rapport à ayant une syntaxe clairement définie.
Giorgio
21

Tout ce que tout le monde dit à propos de la facilité d'ajouter / supprimer / générer des lignes est correct, mais le véritable endroit où cette syntaxe brille est lors de la fusion de fichiers source. Imaginez que vous avez ce tableau:

int ints[] = {
    3,
    9
};

Et supposez que vous avez archivé ce code dans un référentiel.

Ensuite, votre copain le modifie, ajoutant à la fin:

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

Et vous l'éditez simultanément, en ajoutant au début:

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

Sémantiquement, ces types d'opérations (ajout au début, ajout à la fin) devraient être entièrement sécurisés par fusion et votre logiciel de versioning (avec un peu de chance git) devrait pouvoir émerger automatiquement. Malheureusement, ce n'est pas le cas car votre version n'a pas de virgule après le 9 et celle de votre copain. Alors que, si la version originale avait le 9 de fin, ils auraient fusionné automatiquement.

Donc, ma règle de base est: utilisez la virgule de fin si la liste s'étend sur plusieurs lignes, ne l'utilisez pas si la liste est sur une seule ligne.

amoss
la source
15

Je pense que la virgule de fin est autorisée pour des raisons de compatibilité descendante. Il y a beaucoup de code existant, principalement généré automatiquement, qui met une virgule de fin. Cela facilite l'écriture d'une boucle sans condition particulière à la fin. par exemple

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

Il n'y a pas vraiment d'avantage pour le programmeur.

PS Bien qu'il soit plus facile de générer automatiquement le code de cette façon, j'ai toujours pris soin de ne pas mettre la virgule de fin, les efforts sont minimes, la lisibilité est améliorée, et c'est plus important. Vous écrivez du code une fois, vous le lisez plusieurs fois.

Gene Bushuyev
la source
5
Je suis complètement en désaccord; [Je pense que] il a trouvé sa place dans de nombreux langages créés longtemps après C précisément parce qu'il est avantageux pour le programmeur de pouvoir déplacer le contenu du tableau, commenter les lignes à volonté et ainsi de suite, sans avoir à se soucier des erreurs de syntaxe induites par la transposition. Ne sommes-nous pas déjà assez stressés?
Sorti
12
@Dereleased - selon la même logique, pourquoi ne devrait-il pas être autorisé de suivre (quoi que ce soit), que diriez-vous int a = b + c +;ou if(a && b &&);il sera plus facile de simplement copier-coller quoi que ce soit à la fin et plus facile d'écrire des générateurs de code. Ce problème est à la fois trivial et subjectif, dans de tels cas, il est toujours bon de faire ce qui est le mieux pour le lecteur de code.
Gene Bushuyev
1
@Gene Bushuyev: Exactement! J'ai souvent de longues expressions avec + ou &&, avec l'opérateur à la fin de la ligne et, bien sûr, je dois passer un peu plus de temps lorsque je veux supprimer le dernier opérande de l'expression. Je pense que cette syntaxe virgule est vraiment étrange!
Giorgio
2
@GeneBushuyev - Je ne suis pas d'accord sur ces points. Tout en autorisant les virgules de fin dans les tableaux et similaires est une fonctionnalité de suppression de bogues et vous facilite la vie en tant que programmeur, je voudrais, par pur souci de lisibilité, prendre des mesures pour supprimer les instructions ET (&&) de fin, les plus et autres opérateurs divers du conditionnel. déclarations. C'est tout simplement moche, OMI.
Sune Rasmussen
2
En ce qui concerne l' &&opérateur, parfois je fais des conditions comme if (true \n && b1 \n && b2)pour pouvoir ajouter et supprimer des lignes selon mes besoins.
Christian Mann
12

Une des raisons pour lesquelles cela est autorisé à ma connaissance est qu'il devrait être simple de générer automatiquement du code; vous n'avez besoin d'aucune manipulation spéciale pour le dernier élément.

Fredrik Pihl
la source
11

Il facilite les générateurs de code qui crachent des tableaux ou des énumérations.

Imaginer:

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

C'est-à-dire, pas besoin de faire une manipulation spéciale du premier ou du dernier élément pour éviter de cracher la virgule de fin.

Si le générateur de code est écrit en Python, par exemple, il est facile d'éviter de cracher la virgule de fin en utilisant la str.join()fonction:

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

Je suis surpris après tout ce temps, personne n'a cité le manuel de référence annoté C ++ ( ARM ), il dit ce qui suit à propos de [dcl.init] avec emphase:

Il y a clairement trop de notations pour les initialisations, mais chacune semble bien servir un style particulier d'utilisation. La notation = {initializer_list, opt} a été héritée de C et sert bien à l'initialisation des structures de données et des tableaux. [...]

bien que la grammaire ait évolué depuis que ARM a été écrit, l'origine demeure.

et nous pouvons aller à la justification C99 pour voir pourquoi cela a été autorisé en C et il dit:

K&R autorise une virgule de fin dans un initialiseur à la fin d'une liste d'initialiseurs. La norme a conservé cette syntaxe, car elle offre une flexibilité dans l'ajout ou la suppression de membres d'une liste d'initialisation et simplifie la génération par ordinateur de ces listes.

Shafik Yaghmour
la source
1
Votez pour la réponse la plus appuyée par la littérature et la véritable source de cette fonctionnalité.
Marko
10

Je vois un cas d'utilisation qui n'a pas été mentionné dans d'autres réponses, nos macros préférées:

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

L'ajout de macros pour gérer en dernier ,serait très pénible. Avec ce petit changement de syntaxe, cela est trivial à gérer. Et cela est plus important que le code généré par la machine, car il est généralement beaucoup plus facile de le faire dans la langue complète de Turing que le préprocesseur très limité.

Yankes
la source
7

Le seul langage où il est - en pratique * - non autorisé est Javascript, et il provoque une quantité innombrable de problèmes. Par exemple, si vous copiez et collez une ligne du milieu du tableau, collez-la à la fin et oubliez de supprimer la virgule, votre site sera totalement interrompu pour vos visiteurs IE.

* En théorie, il est autorisé mais Internet Explorer ne suit pas la norme et le traite comme une erreur

Thomas Bonini
la source
Les "tableaux" de JavaScript (qui ne sont que des objets avec une propriété de longueur magique) sont de toute façon assez inhabituels: var x = [,,,]est légal (sauf dans IE <9, mais la spécification dit que c'est légal)
Peter C
Selon la spécification ECMAScript, il est parfaitement valide; en théorie, il devrait fonctionner dans tout navigateur qui implémente JavaScript conformément à ladite spécification, en particulier la partie de la spécification trouvée ici .
Sorti
1
Malheureusement, JavaScript consiste à créer des applications pour le public. Donc non, ce n'est pas parfaitement valable lorsque ~ 50% des utilisateurs auraient des problèmes à utiliser votre application. Et oui, si je le pouvais, j'interdirais IE <9 - juste trop d'heures passées à simplement faire travailler un bon code là-bas ...
kgadek
@Dere: oui, je l'ai dit dans ma réponse =)
Thomas Bonini
@Dereleased microsoft invente ses propres spécifications et commandes que les autres respectent au moins que la mentalité est en train de changer (Dieu merci)
Chris McGrath
7

C'est plus facile pour les machines, c'est-à-dire l'analyse et la génération de code. C'est aussi plus facile pour les humains, c'est-à-dire la modification, la mise en commentaire et l'élégance visuelle via la cohérence.

En supposant C, écririez-vous ce qui suit?

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

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

    return EXIT_SUCCESS
}

Non. Non seulement parce que la déclaration finale est une erreur, mais aussi parce qu'elle est incohérente. Alors pourquoi faire de même avec les collections? Même dans les langues qui vous permettent d'omettre les derniers points-virgules et virgules, la communauté n'aime généralement pas cela. La communauté Perl, par exemple, ne semble pas aimer omettre les points-virgules, sauf les lignes simples. Ils l'appliquent également aux virgules.

N'omettez pas de virgules dans les collections multilignes pour la même raison que vous ne supprimez pas les points-virgules pour les blocs de code multilignes. Je veux dire, vous ne le feriez pas même si la langue le permettait, non? Droite?

Louis
la source
Il existe des langages (par exemple Pascal) qui permettent cela. C'est-à-dire que vous devez choisir entre; comme terminateur (C) ou comme séparateur (Pascal). Pareil pour ','. Ce serait bien pour moi si «,» est un terminateur, mais alors {1, 2, 3} doit être une erreur de syntaxe.
Giorgio
6

La raison est banale: facilité d'ajout / suppression de lignes.

Imaginez le code suivant:

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

Maintenant, vous pouvez facilement ajouter / supprimer des éléments à la liste sans avoir à ajouter / supprimer parfois la virgule de fin.

Contrairement à d'autres réponses, je ne pense pas vraiment que la facilité de génération de la liste soit une raison valable: après tout, il est trivial que le code casse la dernière (ou la première) ligne. Les générateurs de code sont écrits une seule fois et utilisés plusieurs fois.

Vlad
la source
6

Il permet à chaque ligne de suivre le même formulaire. Tout d'abord, cela facilite l'ajout de nouvelles lignes et la mise en place d'un système de contrôle de version qui suit les modifications de manière significative et vous permet également d'analyser le code plus facilement. Je ne peux pas penser à une raison technique.

Mark B
la source
5

Cela permet de se protéger des erreurs causées par le déplacement d'éléments dans une longue liste.

Par exemple, supposons que nous ayons un code ressemblant à ceci.

#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;
    }
}

Et c'est génial, car il montre la trilogie originale des sites Stack Exchange.

Stack Overflow
Super User
Server Fault

Mais il y a un problème avec ça. Vous voyez, le pied de page de ce site Web montre une défaillance du serveur avant le super utilisateur. Mieux vaut corriger cela avant que quiconque ne le remarque.

#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;
    }
}

Après tout, déplacer des lignes ne pouvait pas être si difficile, n'est-ce pas?

Stack Overflow
Server FaultSuper User

Je sais, il n'y a pas de site Web appelé "Server FaultSuper User", mais notre compilateur prétend qu'il existe. Maintenant, le problème est que C a une fonctionnalité de concaténation de chaînes, qui vous permet d'écrire deux chaînes entre guillemets doubles et de les concaténer en utilisant rien (un problème similaire peut également se produire avec des entiers, comme- signe a plusieurs significations).

Et si le tableau d'origine avait une virgule inutile à la fin? Eh bien, les lignes seraient déplacées, mais un tel bug ne serait pas arrivé. Il est facile de rater quelque chose d'aussi petit qu'une virgule. Si vous vous souvenez de mettre une virgule après chaque élément du tableau, un tel bogue ne peut tout simplement pas se produire. Vous ne voudriez pas perdre quatre heures à déboguer quelque chose, jusqu'à ce que vous trouviez que la virgule est la cause de vos problèmes .

Konrad Borowski
la source
4

Comme beaucoup de choses, la virgule de fin dans un initialiseur de tableau est l'une des choses que C ++ hérite de C (et devra prendre en charge pour toujours). Une vue totalement différente de celles placées ici est mentionnée dans le livre "Deep C secrets" .

Après un exemple avec plus d'un "paradoxes de virgule":

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? */
};

nous lisons :

... que la virgule de fin après l'initialiseur final n'est pas une faute de frappe, mais une erreur dans la syntaxe transférée du C aborigène . Sa présence ou son absence est autorisée mais n'a aucune signification . La justification revendiquée dans la justification de l'ANSI C est qu'elle facilite la génération automatisée de C. L'allégation serait plus crédible si les virgules de fin étaient autorisées dans chaque liste séparée par des virgules , comme dans les déclarations d'énumération, ou dans plusieurs déclarations de variables dans une seule déclaration. Ils ne sont pas.

... pour moi, cela a plus de sens

Nikos Athanasiou
la source
2
L'interdiction de la virgule dans le enumcas est quelque peu intéressante, car c'est le cas où la virgule manquante poserait le moins d'ambiguïté. Étant donné struct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }; il y a deux significations sensées que la langue pourrait assigner: créer un tableau à deux éléments, ou créer un tableau à trois éléments où le dernier élément a des valeurs par défaut. Si C avait adopté l'interprétation ultérieure, je pourrais voir l'interdiction enum foo {moe, larry, curly, };sur le principe qu'il ne devrait y avoir qu'une seule façon d'écrire la déclaration (sans la virgule), mais ...
supercat
1
... étant donné que C est prêt à ignorer la virgule dans un cas où il aurait pu raisonnablement avoir (mais n'a pas) reçu une signification significative (ce qui serait un argument fort en faveur de l'interdire là), il est curieux que ce ne soit pas ne veut pas dans un cas où la virgule ne pourrait pas avoir de sens [même si l'on interprétait enum foo {moe,,larry,curly,};comme sauter un nombre entre moeet larry, il n'aurait généralement pas d'importance si la virgule de fin a été traitée ou ignorée. Le seul cas où cela pourrait être important serait si le dernier élément était la valeur maximale pour son type déclaré, et que ...
supercat
1
... pourrait être gérée en disant simplement que le débordement qui se produit après la dernière valeur d'énumération attribuée doit être ignoré.
supercat
@supercat Il existe des langages, comme C #, où la recherche de conception a priori va jusqu'à considérer les fonctionnalités et l'intégration IDE lors de la dévolopage du langage. C n'était pas (et n'aurait pas pu être) l'une de ces langues.
Nikos Athanasiou
Même avec des langages comme C #, la modification des objectifs de conception a entraîné des incohérences de conception assez graves. Par exemple, le langage s'est abstenu de prendre en charge toute forme de surcharge de type retour pour les méthodes et opérateurs normaux (même si le cadre sous-jacent pouvait le prendre en charge) car il était considéré comme contraire à l'objectif d'avoir un langage simple à compiler, mais L'évaluation lambda inclut des règles d'inférence de type dont la résolution est NP-complete. L'ajout de nouvelles règles de surcharge de méthode / opérateur pourrait casser le code existant (même si je pense que de bonnes règles pourraient minimiser ce danger) ...
supercat
2

Outre la facilité de génération et d'édition de code, si vous souhaitez implémenter un analyseur, ce type de grammaire est plus simple et plus facile à implémenter. C # suit cette règle à plusieurs endroits: il existe une liste d'éléments séparés par des virgules, comme des éléments dans une enumdéfinition.

Iravanchi
la source
1

Cela facilite la génération de code car vous n'avez besoin d'ajouter qu'une seule ligne et n'avez pas besoin de traiter l'ajout de la dernière entrée comme s'il s'agissait d'un cas spécial. Cela est particulièrement vrai lors de l'utilisation de macros pour générer du code. Il y a une pression pour essayer d'éliminer le besoin de macros de la langue, mais une grande partie de la langue a évolué main dans la main avec des macros disponibles. La virgule supplémentaire permet de définir et d'utiliser des macros telles que les suivantes:

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

Usage:

LIST_BEGIN
   LIST_ENTRY(1)
   LIST_ENTRY(2)
LIST_END

C'est un exemple très simplifié, mais souvent ce modèle est utilisé par des macros pour définir des éléments tels que des cartes et des tableaux de répartition, de message, d'événement ou de traduction. Si une virgule n'était pas autorisée à la fin, nous aurions besoin d'un spécial:

#define LIST_LAST_ENTRY(x) x

et ce serait très difficile à utiliser.

Scott Langham
la source
0

Ainsi, lorsque deux personnes ajoutent un nouvel élément dans une liste sur des branches distinctes, Git peut fusionner correctement les modifications, car Git fonctionne sur une base de ligne.

noɥʇʎԀʎzɐɹƆ
la source
-4

Si vous utilisez un tableau sans longueur spécifiée, VC ++ 6.0 peut automatiquement identifier sa longueur, donc si vous utilisez "int a [] = {1,2,};" la longueur de a est 3, mais la dernière n'a pas ' t été initialisé, vous pouvez utiliser "cout <

zhi_jian
la source
Est-ce un bug pour VC6 qui n'est pas conforme à la norme?
Thomson