62 votes

Effet de l'utilisation d'une virgule au lieu d'un point-virgule en C et C ++

J'ai remarqué à plusieurs reprises lors d'un refactoring de divers morceaux de code C et C++ qu'une virgule est utilisée plutôt qu'une semi-virgule pour séparer les états. Quelque chose comme ceci;

int a = 0, b = 0;
a = 5, b = 5;

Où je me serais attendu

int a = 0, b = 0;
a = 5; b = 5;

Je sais que le C et le C++ permet d'utiliser des virgules pour séparer les états (notamment de la boucle d'en-têtes), mais quelle est la différence si tout entre ces deux morceaux de code? Ma conjecture est que la virgule a été laissé dans le résultat de couper et coller, mais est-ce un bug et qu'il ne effet de l'exécution?

93voto

Frank Points 6174

Il n'est pas de faire une différence dans le code que vous avez posté. En général, la virgule sépare des expressions comme un point-virgule, cependant, si vous prenez le tout comme une expression, l'opérateur virgule signifie que l'expression prend la valeur du dernier argument.

Voici un exemple:

b = (3,5);

Évaluera 3, puis 5 et attribuer à ce dernier de b. Donc b==5. Notez que les parenthèses sont importants ici:

b = 3, 5;

Évaluera b=3, puis 5, et le résultat de l'expression complète est de 5, néanmoins b == 3.

L'opérateur virgule est particulièrement utile pour des boucles lorsque votre itérateur code n'est pas un simple i++, mais vous avez besoin de faire plusieurs commandes. Dans ce cas, un point-virgule ne fonctionne pas bien avec la boucle for de la syntaxe.

22voto

x4u Points 7436

La virgule est un opérateur qui renvoie une valeur qui est toujours le deuxième argument (le droit) alors qu'un point-virgule se termine juste. Cela permet à l'opérateur de virgule d'être utilisé dans d'autres instructions ou de concaténer plusieurs instructions pour qu'elles ne fassent plus qu'une.

Ici, la fonction f (x) est appelée, puis x > y est évalué pour l'instruction if.

 if( y = f(x), x > y )
 

Un exemple quand il est utilisé juste pour éviter le besoin de bloquer

 if( ... )
   x = 2, y = 3;

if( ... ) {
   x = 2;
   y = 3;
}
 

8voto

UncleBens Points 24580

L'opérateur virgule évalue tous les opérandes de gauche à droite, et le résultat est la valeur de la dernière opérande.

Elle est surtout utile pour des boucles si vous voulez faire plusieurs actions de la "incrémenter" partie, de l'e.g (inversion d'une chaîne de caractères)

for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper)
    std::swap(s[lower], s[upper]);

Un autre exemple, où il pourrait être une option (pour trouver toutes les occurrences dans une chaîne de caractères):

#include <string>
#include <iostream>

int main()
{
    std::string s("abracadabra");
    size_t search_position = 0;
    size_t position = 0;

    while (position = s.find('a', search_position), position != std::string::npos) {
        std::cout << position << '\n';
        search_position = position + 1;
    }
}

En particulier, la logique et ne peut pas être utilisé pour cette condition, car à la fois nulle et non nulle peut dire que le personnage a été trouvé dans la chaîne. Avec la virgule, d'autre part, position = s.find() est appelé à chaque fois que la condition est évaluée, mais le résultat de cette partie de la condition est tout simplement ignorés.

Naturellement, il existe d'autres façons d'écrire la boucle:

while ((position = s.find('a', search_position)) != std::string::npos)

ou tout simplement

while (true) {
    position = s.find('a', search_position);
    if (position == std::string::npos)
        break;
    ...
}

4voto

catwalk Points 3508

une utilisation serait dans le code de golf:

 if(x==1)y=2,z=3;
if(x==1){y=2;z=3;}
 

la première ligne est plus courte, mais cela semble trop déroutant pour être utilisé dans un développement régulier

3voto

Michael Burr Points 181287

Comme Frank a mentionné, comment l'opérateur virgule est utilisé dans votre exemple n'est pas une cause d'un bug. L'opérateur virgule peut être source de confusion pour plusieurs raisons:

  • il n'est pas vu trop souvent, car il est seulement nécessaire dans certains cas particuliers
  • il y a plusieurs autres syntaxique utilise de la virgule qui peut ressembler à un opérateur virgule - mais ils ne le sont pas (les virgules sont utilisées pour séparer les paramètres de la fonction/arguments, les virgules servent à séparer les déclarations de variables ou des initialiseurs)

Car c'est source de confusion et souvent inutiles, l'opérateur virgule doit être évitée sauf pour certaines situations très spécifiques:

  • il peut être utile d'effectuer des opération multiple dans l'un ou plus d'un for déclaration de contrôler les expressions
  • il peut être utilisé dans les macros du préprocesseur pour évaluer plus d'une expression dans un seul énoncé. Ceci est généralement fait pour permettre à un des macros pour faire plus d'une chose et d'être toujours une expression unique, de sorte que la macro se tiennent dans des endroits qui ne permettent qu'une expression.

L'opérateur virgule est un hackish opérateur à peu près par définition - c'est à pirater 2 choses où un seul est autorisé. C'est presque toujours moche, mais parfois, c'est tout ce que vous avez. Et c'est le seul moment où vous devriez utiliser si vous avez une autre option, ne pas utiliser l'opérateur virgule.

Sur le dessus de ma tête, je ne peux pas penser à de trop nombreuses autres raisons pour l'utilisation de l'opérateur, puisque vous pouvez obtenir un effet similaire par l'évaluation des expressions dans des déclarations séparées dans la plupart des autres situations (même si je suis sûr que quelqu'un va commenter un autre usage que j'ai oubliées).

Prograide.com

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.

Powered by:

X