Nous pouvons écrire une déclaration if
comme
if (a == 5, b == 6, ... , thisMustBeTrue)
et seule la dernière condition devrait être satisfiable pour entrer dans le corps if
.
pourquoi est-ce permis?
Nous pouvons écrire une déclaration if
comme
if (a == 5, b == 6, ... , thisMustBeTrue)
et seule la dernière condition devrait être satisfiable pour entrer dans le corps if
.
pourquoi est-ce permis?
La modification de votre exemple légèrement, suppose que c'était ce
if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )
(note de l' =
au lieu de ==
). Dans ce cas, les virgules garantir un ordre de gauche à droite de l'évaluation. En contraste, avec cette
if ( thisMustBeTrue(f(5), f(6)) )
vous ne savez pas si f(5)
est appelée avant ou après l' f(6)
.
Plus formellement, des virgules, qui vous permettent d'écrire une séquence d'expressions (a,b,c)
de la même façon, vous pouvez utiliser ;
d'écrire une suite d'instructions, a; b; c;
.
Et juste comme un ;
crée un point de séquence (à la fin de la pleine expression) aussi une virgule. Seule la séquence de points régissent l'ordre d'évaluation, voir ce post.
Mais bien sûr, dans ce cas, vous fait écrire ce
a = f(5);
b = f(6);
if ( thisMustBeTrue(a, b) )
Alors, quand est, séparés par des virgules séquence d'expressions préférable à un ;
séparés séquence d'instructions? Presque jamais, je dirais. Peut-être dans une macro lorsque vous voulez le côté droit, en remplacement d'une seule expression.
En bref:
Même si il est légal de le faire, il n'a généralement pas de sens d'utiliser l'opérateur virgule en l'état partie d' if
ou while
déclaration (EDIT: Même si ce dernier peut parfois être utile comme user5534870 explique dans sa réponse).
Une version plus élaborée explication:
Outre sa fonction syntaxique (par exemple, éléments de séparation dans l'initialiseur de listes, les déclarations de variables ou des appels de fonction/déclarations), en C et C++, l' ,
peut également être sur un opérateur, comme par exemple, +
, et il peut donc être utilisé partout où une expression est autorisée (en C++, vous pouvez même la surcharge).
La différence de la plupart des autres opérateurs, c'est que - bien que les deux côtés sont évaluées - il ne pas combiner les sorties de la gauche et la droite expressions en aucune façon, mais renvoie simplement le droit.
Il a été introduit, parce que quelqu'un (probablement Dennis Ritchie) a décidé, pour quelque raison que C une syntaxe pour écrire deux (ou plus) sans rapport avec les expressions à une position où d'ordinaire pouvait écrire une expression unique.
Maintenant, la condition d'une if
déclaration est (entre autres) un tel endroit et, par conséquent, vous pouvez également utiliser l' ,
opérateur y - si cela a du sens de le faire ou pas est une question entièrement différente! En particulier - et les différents provenant, par exemple, les appels de fonction ou de déclarations de variables - la virgule n'a pas de signification particulière, de sorte qu'il fait, ce qu'il a toujours fait: Il évalue les expressions à gauche et à droite, mais seulement renvoie le résultat de la droite, qui est ensuite utilisé par l' if
déclaration.
Les deux seuls points que je pense maintenant, où à l'aide de la (non surchargé) ,
-opérateur de sens que sont:
Si vous voulez incrémenter plusieurs itérateurs dans la tête d'un for
boucle:
for ( ... ; ... ; ++i1, ++i2){
*i2=*i1;
}
Si vous voulez évaluer plus d'une expression en C++11 constexpr fonction.
Pour répéter une fois de plus: à l'Aide de l'opérateur virgule en if
ou while
énoncé dans la façon dont vous l'a montré dans votre exemple - n'est-ce pas quelque chose d'intelligent à faire. Il est juste un autre exemple où le langage de syntaxe de C et C++ vous permettent d'écrire du code, qui ne se comportent pas de la manière que le premier coup d'œil - attendez. Il ya beaucoup plus....
Pour un if
déclaration, il n'y a pas de véritable point de mettre quelque chose dans une virgule expression plutôt qu'à l'extérieur.
Pour un while
déclaration, mettre une virgule expression de la condition exécute la première partie , soit lors de l'entrée de la boucle, ou si la boucle. Qui ne peuvent pas facilement être reproduit sans duplication de code.
Alors, comment un s do
...while
déclaration? Il nous ont seulement à vous soucier de la boucle elle-même, non? Il s'avère que même pas ici une virgule expression peut être remplacer en toute sécurité par le déplacement de la première partie dans la boucle.
Pour une chose, destructeurs pour les variables dans le corps de la boucle n'auront pas déjà été exécuté, alors qui peut faire une différence. Pour un autre, tout continue
déclaration à l'intérieur de la boucle atteindra la première partie de la virgule expression uniquement lorsqu'il est en effet dans l'état plutôt que dans le corps de la boucle.
Il n'y a aucun avantage : l'opérateur virgule est simplement une expression avec le type de la dernière expression dans sa liste d'expressions et une instruction if évalue une expression booléenne.
if(<expr>) { ... }
with type of <expr> boolean
C'est un opérateur étrange, mais il n'y a pas de magie - sauf qu'il confond les listes d'expressions avec les listes d'arguments dans les appels de fonctions.
foo(<args>)
with <args> := [<expr>[, <expr>]*]
Notez que dans la liste des arguments, la virgule se lie davantage à la séparation des arguments.
Ce qui suit est un peu exagéré, selon la façon dont rusé, vous pourriez être.
Considérons une situation où une fonction retourne une valeur en modifiant un paramètre passé par référence ou par pointeur (peut-être d'un mal conçu de la bibliothèque, ou pour s'assurer que cette valeur n'est pas ignorée par ne pas être affecté après son retour, peu importe).
void calculateValue(FooType &result) {/*...*/}
Alors, comment utilisez-vous les instructions conditionnelles qui dépendent result
?
Vous pouvez déclarer la variable qui va être modifié, puis vérifier avec un si:
FooType result;
calculateValue(result);
if (result.isBared()) {
//...
}
Ce pourrait être réduit à
FooType result;
if (calculateValue(result) , result.isBared()) {
//...
}
Ce qui n'est pas vraiment la peine. Cependant, pour while
boucles il pourrait y avoir quelques petits avantages. Si calculateValue
doit-on/peut être appelé jusqu'à ce que le résultat n'est plus bar
'd, nous aurions quelque chose comme:
FooType result;
calculateValue(result); //[1] Duplicated code, see [2]
while (result.isBared()) {
//... possibly many lines
//separating the two places where result is modified and tested
//How do you prevent someone coming after you and adds a `continue`
//here which prevents result to be updated in the and of the loop?
calculateValue(result); //[2] Duplicated code, see [1]
}
et pourrait être condensé:
FooType result;
while (calculateValue(result) , result.isBared()) {
//all your (possibly numerous) code lines go here
}
De cette façon, le code pour mettre à jour result
est en un seul endroit, et est près de la ligne de où ses conditions sont vérifiées.
peut-être sans rapport avec: une Autre raison pour laquelle les variables pourrait être mis à jour via le paramètre passant, c'est que la fonction doit retourner le code d'erreur en plus de modifier/retourne la valeur calculée. Dans ce cas:
ErrorType fallibleCalculation(FooType &result) {/*...*/}
alors
FooType result;
ErrorType error;
while (error = fallibleCalculation(result) , (Success==error && result.isBared())) {
//...
}
mais comme il est noté dans les commentaires, vous pouvez le faire sans la virgule de trop:
FooType result;
ErrorType error;
while (Success == fallibleCalculation(result) && result.isBared()) {
//...
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.