Que fait l' ,
opérateur en C?
c
operators
comma-operator
Lillq
la source
la source
Réponses:
L'expression:
La première expression1 est évaluée, puis expression2 est évaluée et la valeur de expression2 est renvoyée pour l'expression entière.
la source
i
les valeurs 5, 4, 3, 2 ou 1. C'est simplement 0. C'est pratiquement inutile à moins que les expressions aient des effets secondaires.i = b, c;
équivaut à(i = b), c
parce que l'attribution=
a une priorité plus élevée que l'opérateur virgule,
. L'opérateur virgule a la priorité la plus basse de tous.expression1, expression2;
abordexpression1
est évalué, probablement pour ses effets secondaires (comme l'appel d'une fonction), puis il y a un point de séquence, puisexpression2
est évalué et la valeur est renvoyée…J'ai vu le plus utilisé dans les
while
boucles:Il fera l'opération, puis fera un test basé sur un effet secondaire. L'autre façon serait de le faire comme ceci:
la source
while (read_string(s) && s.len() > 5)
. De toute évidence, cela ne fonctionnerait pas siread_string
n'a pas de valeur de retour (ou n'a pas de valeur significative). (Edit: Désolé,while (1)
avec unebreak;
déclaration dans le corps. Essayer de forcer la partie break-out du code dans le test while ou dans le test do-while, est souvent un gaspillage d'énergie et rend le code plus difficile à comprendre.while(1)
etbreak
;L' opérateur virgule évaluera l'opérande gauche, rejettera le résultat, puis évaluera l'opérande droit et ce sera le résultat. L' utilisation idiomatique comme indiqué dans le lien est lors de l'initialisation des variables utilisées dans une
for
boucle, et il donne l'exemple suivant:Sinon, il n'y a pas beaucoup de bonnes utilisations de l' opérateur virgule , bien qu'il soit facile d'abuser de générer du code difficile à lire et à maintenir.
À partir du projet de norme C99, la grammaire est la suivante:
et le paragraphe 2 dit:
La note de bas de page 97 dit:
ce qui signifie que vous ne pouvez pas affecter le résultat de l' opérateur virgule .
Il est important de noter que l'opérateur virgule a la priorité la plus basse et qu'il existe donc des cas où l'utilisation
()
peut faire une grande différence, par exemple:aura la sortie suivante:
la source
L'opérateur virgule combine les deux expressions de chaque côté en une seule, en les évaluant toutes les deux dans l'ordre de gauche à droite. La valeur du côté droit est renvoyée comme valeur de l'expression entière.
(expr1, expr2)
est similaire{ expr1; expr2; }
mais vous pouvez utiliser le résultat deexpr2
dans un appel ou une affectation de fonction.On le voit souvent dans des
for
boucles pour initialiser ou maintenir plusieurs variables comme ceci:En dehors de cela, je ne l'ai utilisé «en colère» que dans un autre cas, lors de la conclusion de deux opérations qui devraient toujours aller ensemble dans une macro. Nous avions du code qui copiait diverses valeurs binaires dans un tampon d'octets pour l'envoi sur un réseau, et un pointeur maintenu là où nous en étions:
Là où les valeurs étaient
short
s ouint
s, nous avons fait ceci:Plus tard, nous avons lu que ce n'était pas vraiment un C valide, car ce
(short *)ptr
n'est plus une valeur l et ne peut pas être incrémenté, bien que notre compilateur à l'époque ne s'en soit pas soucié. Pour résoudre ce problème, nous avons divisé l'expression en deux:Cependant, cette approche reposait sur le fait que tous les développeurs se souvenaient de mettre les deux déclarations tout le temps. Nous voulions une fonction où vous pourriez passer le pointeur de sortie, la valeur et et le type de la valeur. Ceci étant C, pas C ++ avec des modèles, nous ne pouvions pas avoir une fonction prendre un type arbitraire, nous nous sommes donc installés sur une macro:
En utilisant l'opérateur virgule, nous avons pu l'utiliser dans des expressions ou comme instructions comme nous le souhaitions:
Je ne dis pas qu'aucun de ces exemples n'est de bon style! En effet, il me semble me souvenir de Code Complete de Steve McConnell déconseillant même d'utiliser des opérateurs de virgule dans une
for
boucle: pour la lisibilité et la maintenabilité, la boucle doit être contrôlée par une seule variable, et les expressions dans lafor
ligne elle-même ne doivent contenir que du code de contrôle de boucle, pas d'autres bits supplémentaires d'initialisation ou de maintenance de boucle.la source
Cela provoque l'évaluation de plusieurs déclarations, mais n'utilise que la dernière comme valeur résultante (rvalue, je pense).
Alors...
devrait aboutir à la mise à 8 de x.
la source
Comme les réponses précédentes l'ont indiqué, il évalue toutes les déclarations mais utilise la dernière comme valeur de l'expression. Personnellement, je ne l'ai trouvé utile que dans les expressions de boucle:
la source
Le seul endroit où je l'ai vu être utile est lorsque vous écrivez une boucle funky où vous voulez faire plusieurs choses dans l'une des expressions (probablement l'expression init ou l'expression de la boucle. Quelque chose comme:
Pardonnez-moi s'il y a des erreurs de syntaxe ou si j'ai mélangé quelque chose qui n'est pas strict C. Je ne dis pas que l'opérateur, est de bonne forme, mais c'est pour cela que vous pouvez l'utiliser. Dans le cas ci-dessus, j'utiliserais probablement une
while
boucle à la place, de sorte que les multiples expressions sur init et loop seraient plus évidentes. (Et j'initialiserais i1 et i2 en ligne au lieu de déclarer puis d'initialiser .... bla bla bla.)la source
Je le ressuscite simplement pour répondre aux questions de @Rajesh et @JeffMercado qui, à mon avis, sont très importantes car c'est l'un des meilleurs résultats des moteurs de recherche.
Prenons par exemple l'extrait de code suivant
Il imprimera
Le
i
cas est traité comme expliqué par la plupart des réponses. Toutes les expressions sont évaluées dans l'ordre de gauche à droite, mais seule la dernière est affectéei
. Le résultat de l'(
expression )is
1`.Le
j
cas suit des règles de priorité différentes car il,
a la priorité d'opérateur la plus basse. En raison de ces règles, le compilateur voit l' expression d'affectation, constante, constante ... . Les expressions sont évaluées à nouveau dans l' ordre et leurs effets secondaires à droite gauche restent visibles, doncj
est5
en raison dej = 5
.Fait intéressant,
int j = 5,4,3,2,1;
n'est pas autorisé par la spécification de la langue. Un initialiseur attend une expression d'affectation, donc un,
opérateur direct n'est pas autorisé.J'espère que cela t'aides.
la source