int a[] = {1,2,}; Bizarre virgule permis. Une raison en particulier?
Peut-être que je ne suis pas de cette planète, mais il me semble que la suite devrait être une erreur de syntaxe:
int a[] = {1,2,}; //extra comma in the end
Mais il ne l'est pas. J'ai été surpris lorsque ce code est compilé sur Visual Studio, mais j'ai appris à ne faire confiance à MSVC compilateur dans la mesure du C++ les règles, j'ai donc vérifié la norme, et qu'elle est autorisé par la norme. Vous pouvez voir 8.5.1 pour les règles de grammaire si vous ne me croyez pas.
Pourquoi est-ce possible? Cela peut sembler stupide, inutile, mais je veux que vous compreniez pourquoi je demande. Si c'était un sous-cas général règle de grammaire, je le comprends ils ont décidé de ne pas faire de la grammaire générale plus difficile de refuser un redondante virgule à la fin d'une liste d'initialiseur. Mais non, la virgule supplémentaire est explicitement permis. Par exemple, il n'est pas permis d'avoir une redondance virgule à la fin d'une fonction-appel de la liste d'arguments (quand la fonction prend ...
), ce qui est normal.
Donc, encore une fois, est-il une raison particulière à cette redondant virgule est explicitement permis?
;
quand il est clair prochain jeton est effectivement une instruction suivante.Oui, la langue concepteurs de considérer de telles choses. Vous permettant de déposer des points-virgules aurait un impact beaucoup plus important et serait très ambigu dans de nombreuses parties de la langue (rappelez-vous, l'espace n'est pas sémantique en C). Une virgule supplémentaire est ce cas n'est pas ambigu. Un supplément de point-virgule est presque jamais ambigu, et est donc autorisé. Dans le cas où il est ambigu (après un
for()
par exemple), ajoutant qu'il lance un avertissement du compilateur.Il est ambigu pour un lecteur humain, et 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ë à l'homme, et donc jette un avertissement.Votre
if
exemple n'est pas ambigu. Je ne pense pas que "ambigu" les moyens ce que vous pensez que cela signifie!Aussi longtemps que nous sommes d'accord que c'est quelque chose d'utile pour le compilateur pour nous protéger, alors qu'une virgule dans une déclaration de tableau n'est pas quelque chose d'utile pour le compilateur pour nous protéger.
OriginalL'auteur Armen Tsirunyan | 2011-08-12
Vous devez vous connecter pour publier un commentaire.
Il est plus facile de générer du code source, et aussi d'écrire du code qui peut être facilement étendu à une date ultérieure. Considérer ce qui est nécessaire pour ajouter une entrée supplémentaire:
... vous devez ajouter la virgule à la ligne existante et ajouter une nouvelle ligne. Comparer avec le cas où les trois déjà a une virgule après elle, où vous avez juste à ajouter une ligne. De même, si vous souhaitez supprimer une ligne, vous pouvez le faire sans se soucier de savoir si c'est la dernière ligne ou pas, et vous pouvez réorganiser les lignes sans besoin de se battre avec des virgules. Fondamentalement, cela signifie qu'il y a une uniformité dans la façon dont vous traitez les lignes.
Maintenant, pensez à la génération de code. Quelque chose comme (pseudo-code):
Pas besoin de s'inquiéter de savoir si l'actuel article que vous écrivez est le premier ou le dernier. Beaucoup plus simple.
Pourquoi "malheureux"? Quel est l'inconvénient ici? Juste parce qu'il a été donné à la génération de code (et facile de manipulation) pour une petite partie de la langue ne signifie pas qu'il doit être la principale motivation derrière toutes les décisions de la langue. L'inférence de Type, le retrait de points-virgules etc énorme implications pour la langue. Vous êtes en train de configurer une fausse dichotomie ici, de l'OMI.
C'est là où le pragmatisme l'emporte sur le dogmatisme: pourquoi a-t-il d'être entièrement ou entièrement de l'autre, quand c'est plus utile pour être un mélange des deux? Comment est-ce vraiment obtenir de la manière, être en mesure d'ajouter une virgule à la fin? Est-ce une incohérence qui ne l'a jamais empêché de vous dans tous les sens? Si non, veuillez peser non pertinentes inelegance à l'encontre de la pratique avantages de permettre une virgule à la fin.
Il ne s'agit pas de taper taux - c'est une question de simplicité, lors de la copie, la suppression ou la réorganisation des éléments. Il m'a rendu la vie plus simple de juste hier. Avec aucun inconvénient, pourquoi pas rendre la vie plus facile? Comme pour essayer de pointer du doigt les MS, je soupçonne fortement que ce qui a été en C depuis avant que Microsoft a même existé... Vous dire que cette justification semble bizarre, mais je parie que c'avantages des milliers de développeurs à travers des centaines de sociétés de tous les jours. N'est-ce pas une meilleure explication que la recherche de quelque chose qui profite à compilateur écrivains?
C'était dans le K&R C.
OriginalL'auteur Jon Skeet
C'est utile si vous faites quelque chose comme cela:
var a = [1, 2,];
, de sorte que la plupart des autres langues que je connais... ActionScript, Python, PHP.Cela va provoquer une erreur d'analyse dans IE JavaScript, alors méfiez-vous!
Il n'est pas pour moi dans IE9. Mais il fait quelque chose d'étrange... il crée un élément de valeur null. Je vais méfiez-vous.
Désolé, vous avez raison - ce n'est pas une erreur d'analyse dans IE, mais insérer un élément supplémentaire mis à
undefined
.Le plus frustrant, JSON ne supporte pas cette syntaxe.
OriginalL'auteur Skilldrick
La facilité d'utilisation pour les développeurs, je pense.
En outre, si, pour quelque raison que ce soit vous aviez un outil que le code généré pour vous; l'outil n'avez pas à vous soucier de savoir si c'est le dernier élément de l'initialiser ou non.
OriginalL'auteur vcsjones
J'ai toujours supposé qu'il le rend plus facile d'ajouter des éléments supplémentaires:
devient tout simplement:
à une date ultérieure.
Eh bien, c'est héritée de C. Il est tout à fait possible que c'est juste un oubli dans la langue d'origine de la spécification, qui arrive à avoir un côté utile à effet.
Ok, je ne savais pas qu'il vient de C. je viens de vérifier qu'il est autorisé en Java, trop. Il se sent un peu bizarre mais: dans mon intuition, la virgule est un séparateur, pas un terminator. En outre, il est possible d'omettre la dernière virgule. Donc, c'est un terminator, un séparateur, ou les deux? Mais OK, cette fonctionnalité est disponible et il est bon à savoir.
le code source est pour les humains, pas des machines. Peu de choses de ce genre pour nous empêcher de prendre de simples erreurs de transposition sont une bénédiction, pas une surveillance. Pour référence, il fonctionne aussi de cette façon en PHP et ECMAScript (et, par conséquent, JavaScript et ActionScript), même si elle n'est pas valide en JavaScript object notation (JSON) (par exemple,
[1,2,3,]
est OK, mais{a:1, b:2, c:3,}
ne l'est pas).Plus j'y pense et plus je suis convaincu que la syntaxe d'un langage de programmation devrait être aussi simple et cohérent que possible et avec le moins d'exceptions que possible: cela rend plus facile à apprendre la langue (de moins en moins de règles à retenir). L'avantage de sauvegarder une ou deux frappes de touches lors de l'ajout / suppression d'un élément à une liste (qui, en passant, je ne le fais pas souvent par rapport à la quantité totale de temps que je passe de codage) semble plutôt banal pour moi par rapport à avoir clairement défini la syntaxe.
OriginalL'auteur Oliver Charlesworth
Tout tout le monde a dit à propos de la facilité d'ajout/suppression/création de lignes est correcte, mais le lieu réel de cette syntaxe brille est lors de la fusion de fichiers source d'ensemble. Imaginez que vous avez ce tableau:
Et supposons que vous avez vérifié ce code dans un référentiel.
Alors votre copain l'édite, en ajoutant à la fin:
Et vous modifier simultanément, en lui ajoutant des le début:
Sémantiquement ces sortes d'opérations (en ajoutant au début, en ajoutant à la fin), devrait être entièrement fusion et de la gestion des versions de logiciels (heureusement git) devrait être en mesure de automerge. Malheureusement, ce n'est pas le cas parce que votre version n'a pas de virgule après le 9 et votre copain n'. Considérant que, si la version d'origine a l'arrière 9, ils auraient automerged.
Donc, ma règle d'or est: l'utilisation de la virgule si la liste s'étend sur plusieurs lignes, ne l'utilisez pas si la liste est sur une seule ligne.
OriginalL'auteur amoss
Virgule, je crois, est autorisé pour des raisons de compatibilité descendante. Il y a beaucoup de code existant, principalement générés automatiquement, ce qui met une virgule. Il facilite l'écriture d'une boucle sans condition particulière, à la fin.
par exemple,
Il n'est pas vraiment un avantage pour le programmeur.
P. S. Bien qu'il est plus facile de générer automatiquement le code de cette façon, j'ai toujours pris soin de ne pas mettre la virgule, les efforts sont minimes, la lisibilité est améliorée, et c'est plus important. Vous écrivez du code une fois, vous avez lu à de nombreuses reprises.
par la même logique, pourquoi ne pas en arrière (rien) être autorisé, que diriez -
int a = b + c +;
ouif(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. Cette question est à la fois trivial et subjective, dans de tels cas, il est toujours bon de faire ce qui est mieux pour le lecteur de code.Bushuyev: Exactement! J'ai souvent des expressions longues avec + ou &&, avec l'opérateur à la fin de la ligne et, bien sûr, je dois passer un peu de temps quand je veux supprimer le dernier des opérandes de l'expression. Je pense que cette virgule syntaxe est vraiment bizarre!
Je suis en désaccord sur ceux-ci. Tout en permettant des virgules dans les tableaux et les aime, c'est un bug de supprimer la fonctionnalité et rend votre vie plus facile en tant que programmeur, je le ferais pour le pur souci de lisibilité prendre des mesures pour retirer de fuite ET (&&) les déclarations, les agréments et les autres opérateurs à partir des instructions conditionnelles. C'est tout simplement laid, de l'OMI.
Concernant la
&&
opérateur, parfois je ne le conditionnel commeif (true \n && b1 \n && b2)
afin que je puisse ajouter et supprimer des lignes que j'ai besoin.OriginalL'auteur Gene Bushuyev
L'une des raisons pour cela est autorisé pour autant que je sais, c'est qu'il devrait être simple de générer automatiquement du code; vous n'avez pas besoin d'un traitement spécial pour le dernier élément.
OriginalL'auteur Fredrik Pihl
Il fait des générateurs de code qui crache des tableaux ou des énumérations plus facile.
Imaginer:
I. e., pas besoin de faire un traitement spécial des premier ou le dernier élément pour éviter de cracher la virgule.
Si le générateur de code est écrit en Python, par exemple, il est facile d'éviter de cracher de la virgule en utilisant
str.join()
fonction:OriginalL'auteur Maxim Egorushkin
Je suis surpris, après tout ce temps personne n'a cité le Annoté C++ Manuel De Référence(BRAS), il est dit ce qui suit au sujet de [dcl.init] avec l'accent de la mine:
bien que la grammaire a évolué depuis BRAS a été écrit à l'origine en reste.
et nous pouvons aller à la C99 justification pour voir pourquoi il a été autorisé en C et il dit:
OriginalL'auteur Shafik Yaghmour
La seule langue où il est en pratique* - non autorisée est de Javascript, et il provoque une innombrable quantité de problèmes. Par exemple, si vous copiez & coller une ligne à partir du milieu du tableau, de le coller à la fin, et j'ai oublié de supprimer la virgule, alors votre site sera complètement cassée de votre IE visiteurs.
*En théorie, il est permis, mais Internet Explorer ne respecte pas la norme et la traite comme une erreur
var x = [,,,]
est légal (sauf dans IE < 9, mais la spec dit que c'est légal)Selon la spécification ECMAScript, il est parfaitement valable; en théorie, il faut travailler dans n'importe quel navigateur qui implémente JavaScript, d'après la spécification, en particulier la partie de la spécification trouvé ici.
Malheureusement, le JavaScript est tout au sujet de faire des applications pour le grand public. Donc non, il n'est pas parfaitement valide lorsque ~50% des utilisateurs ont des problèmes à l'aide de votre application. Et oui, si je le pouvais, je serais ban IE < 9 -- juste beaucoup trop d'heures passées sur juste faire bon code d'y travailler...
oui, j'ai dit que beaucoup dans ma réponse =)
microsoft invente son propre cahier des charges et les commandes que les autres respectent au moins que la mentalité est en train de changer (dieu merci)
OriginalL'auteur Thomas Bonini
C'est plus facile pour les machines, c'est à dire l'analyse et la génération de code.
Il est également plus facile pour les humains, c'est à dire de modification, de les commenter, et le visuel de l'élégance grâce à la cohérence.
En supposant que C, seriez-vous d'écrire la suite?
Pas. Pas seulement parce que l'état final est une erreur, mais aussi parce que c'est incohérent. Alors pourquoi faire de même pour les collections? Même dans les langues qui vous permet d'omettre la dernière des points-virgules et les virgules, la communauté a l'habitude de ne l'aime pas. La communauté Perl, par exemple, ne semble pas aimer l'omission des points-virgules, bar one-liners. Ils appliquent que pour des virgules.
N'omettez pas de virgules dans multiligne collections pour la même raison, vous n'avez pas omettre des points-virgules pour multiligne blocs de code. Je veux dire, vous ne pouvez pas le faire, même si la langue a permis, non? Droit?
OriginalL'auteur Louis
J'en vois un cas d'utilisation qui n'a pas été mentionné dans d'autres réponses,
notre favori des Macros:
L'ajout de macros pour gérer à la dernière
,
serait une grande douleur. Avec ce petit changement dans la syntaxe c'est facile à gérer. Et c'est plus important que la machine généré code, car il est généralement beaucoup plus facile de le faire dans Turing langue que très limitée preprocesor.OriginalL'auteur Yankes
La raison est simple: la facilité d'ajout/suppression de lignes.
Imaginez le code suivant:
Maintenant, vous pouvez facilement ajouter/supprimer des éléments de la liste sans avoir à ajouter/supprimer la virgule parfois.
Contrairement à d'autres réponses, je ne pense vraiment pas que la facilité de génération de la liste est une raison valable: après tout, il est trivial pour que le code spécial de la dernière (ou première) ligne. -Générateurs de Code sont écrits à la fois et utilisé de nombreuses fois.
OriginalL'auteur Vlad
Elle permet à chaque ligne à suivre la même forme. Tout d'abord cela rend plus facile d'ajouter de nouvelles lignes et de disposer d'un système de contrôle de version piste de la modifier de manière significative et il vous permet également d'analyser le code plus facilement. Je ne peux pas penser à une raison technique.
OriginalL'auteur Mark B
Il est permis de le protéger contre les erreurs causées par le déplacement d'éléments dans une liste.
Par exemple, imaginons que nous avons un code qui ressemble à ceci.
Et c'est génial, car il montre que la trilogie originale de la Pile des sites d'Échange.
Mais il y a un problème avec elle. Vous voyez, le pied de page sur ce site web montre de Serveur Faute avant le Super Utilisateur. Mieux corriger ça avant que quelqu'un ne le remarque.
Après tout, le déplacement des lignes autour ne pouvait pas être si difficile que ça, pourrait-il être?
Je sais, il n'y a pas de site web appelé "Serveur FaultSuper Utilisateur", mais notre compilateur prétend qu'il existe. Maintenant, le problème est que C est une concaténation de chaîne automatique, qui vous permet d'écrire deux chaînes entre guillemets doubles et les concaténer en utilisant rien d'autre (même problème peut également se produire avec des nombres entiers, comme
-
signe a plusieurs sens).Maintenant, si le tableau d'origine avait une inutile virgule à la fin? Ainsi, les lignes seraient déplacés, mais tel bug ne serait pas arrivé. Il est facile de rater quelque chose d'aussi petit qu'une virgule. Si vous n'oubliez pas de mettre une virgule après chaque élément du tableau, tel bug juste ne peut pas se produire. Vous ne veulent pas perdre de quatre heures de débogage quelque chose, jusqu'à ce que vous trouver la virgule est la cause de vos problèmes.
OriginalL'auteur Konrad Borowski
Comme pour beaucoup de choses, la virgule dans un initialiseur de tableau est l'une des choses C++ hérité de C (et sont à la charge pour toujours). Un point de vue totalement différents de ceux placés ici est mentionné dans le livre "de Profondeur C secrets".
Y après un exemple avec plus d'une "virgule paradoxes" :
nous lisons :
... pour moi, cela fait plus de sens
enum
cas est assez intéressant, puisque c'est le cas où le manque de virgule poserait le moins d'ambiguïté. Compte tenu destruct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }
; il y a deux sensée significations de la langue pourrait affecter: créer un tableau à deux éléments, ou en créer un à trois éléments de tableau où le dernier élément a des valeurs par défaut. Si C avait adopté l'interprétation récente, j'ai pu voir interdisantenum foo {moe, larry, curly, };
sur le principe qu'il ne devrait être qu'une façon d'écrire l'instruction (sans la virgule), mais......étant donné que C est prêts à ignorer la virgule dans le cas où il aurait raisonnablement pu être (mais n'est-ce pas) a attribué une signification (ce qui serait un argument fort en faveur de l'interdiction de là) il est curieux qu'elle n'est pas disposée dans un cas où la virgule ne pouvais pas avoir un sens (même si on interprète
enum foo {moe,,larry,curly,};
comme le fait de sauter un nombre entremoe
etlarry
, il ne serait généralement pas la question de savoir si la virgule a été traitée ou négligée. Le seul cas où il pourrait en question serait si le dernier élément est la valeur maximale de son type déclaré, et que......pourrait être manipulés en disant simplement que le trop-plein qui se produit à la suite de la dernière valeur de l'énumération doit être ignorée.
Il y a des langages, comme le C#, où la conception a priori de la recherche va aussi loin que de considérer IDE fonctionnalités et de l'intégration lors de la devoloping la langue. C ne l'est pas (et ne pouvait pas ont été) l'une de ces langues.
Même avec des langages comme C#, la modification de la conception, les objectifs ont abouti, dans certains assez graves incohérences de conception. Par exemple, la langue s'est abstenu de soutenir toute forme de retour de type surcharge de méthodes normales et les opérateurs (même si le cadre sous-jacent pourrait le soutenir), car il était considéré comme contraire à l'objectif de disposer d'une simple compilation de la langue, mais lambda évaluation comprend le type de règles d'inférence dont la résolution est NP-complet. L'ajout de nouvelles de la méthode/de la surcharge d'opérateur règles de casser le code existant (même si je pense que les bonnes règles de nature à minimiser ce danger)...
OriginalL'auteur Nikos Athanasiou
En plus à la génération de code et l'édition de facilité, si vous souhaitez mettre en place un analyseur, ce type de grammaire est plus simple et plus facile à mettre en œuvre. C# suit cette règle à plusieurs endroits qu'il y a une liste séparée par des virgules des éléments, comme les éléments d'une
enum
définition.OriginalL'auteur Iravanchi
Il permet de générer le code est plus facile que vous avez seulement besoin d'ajouter une ligne et n'avez pas besoin de traiter l'ajout de la dernière entrée, comme si c'était un cas spécial. Cela est particulièrement vrai lors de l'utilisation de macros pour générer le code. Il y a une poussée d'essayer d'éliminer la nécessité pour les macros de la langue, mais beaucoup de la langue a fait évoluer main dans la main avec les macros disponibles. La virgule supplémentaire permet de macros telles que les suivantes pour être définis et utilisés:
Utilisation:
C'est un exemple simplifié, mais souvent ce modèle est utilisé par des macros pour définir des choses telles que le mode d'expédition, de message, de l'événement ou de la traduction des cartes et des tableaux. Si une virgule n'était pas autorisé à la fin, nous aurions besoin d'un spécial:
et qui serait très difficile à utiliser.
OriginalL'auteur Scott Langham
Si vous utilisez un tableau sans longueur spécifiée,VC++6.0 peut automatiquement identifier sa longueur,de sorte que si vous utilisez "int a[]={1,2,};"la longueur est de 3,mais ce dernier n'a pas été initialisée,vous pouvez utiliser le "cout<
OriginalL'auteur zhi_jian