2010-01-18 28 views
48

Me he dado cuenta en varias ocasiones al refaccionar varias piezas de código C y C++ que se usa una coma en lugar de un punto y coma para separar las declaraciones . Algo como esto;Efecto de usar una coma en lugar de un punto y coma en C y C++

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

Cuando yo habría esperado

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

Sé que C y C++ permiten el uso de comas para separar las declaraciones (en particular los encabezados de asa), pero ¿cuál es la diferencia si los hay entre estas dos piezas de ¿código? Mi suposición es que la coma se ha dejado como resultado de cortar & pegando, pero ¿es un error y afecta la ejecución?

+8

Vale la pena mencionar que el "operador de coma" en la segunda línea es semánticamente diferente de la coma que delimita las expresiones de inicialización en 'int a = 0, b = 0;'. –

+1

También existe este problema con el operador de coma en el sentido de que 'int * a, b;' no es lo mismo que 'int * a; int * b; ' – JPvdMerwe

+2

Es por eso que siempre pongo el puntero/modificador de referencia junto a la variable, no el tipo. 'int * a, b;' – mskfisher

Respuesta

74

No hace una diferencia en el código que envió. En general, la coma separa expresiones como un punto y coma, sin embargo, si toma el todo como una expresión, entonces el operador de coma significa que la expresión se evalúa como el último argumento.

He aquí un ejemplo:

b = (3,5); 

Evaluará 3, luego 5 y asignar éste a b. Entonces b == 5. Tenga en cuenta que los soportes son importantes aquí:

b = 3, 5; 

Evaluará b = 3, luego 5 y el resultado de toda la expresión es 5, sin embargo b == 3.

El operador coma es especialmente útil en for-loops cuando su código de iterador no es un simple i ++, pero necesita hacer varios comandos. En ese caso, un punto y coma no funciona bien con la sintaxis for-loop.

+8

+1: para el 'evalúa el último argumento. – jldupont

+1

+1, buena explicación. Solo quiero agregar un error común que podría ser útil si se trata de muchos de estos: escribir 'a [j, k]' en lugar de 'a [j] [k]' generalmente conduce a resultados no deseados. – laura

+0

Bueno, técnicamente la coma es un operador binario, por lo que solo tiene una expresión izquierda y derecha. Pero cuando se usan varias comas en el mismo nivel, el resultado recursivo es en realidad que se evalúa como la última expresión. – x4u

20

La coma es un operador que devuelve un valor que siempre es el segundo argumento (a la derecha) mientras que un punto y coma acaba con las declaraciones. Eso permite que el operador de coma se use dentro de otras instrucciones o para concatenar varias declaraciones para que aparezcan como una sola.

Aquí se llama a la función f (x) y luego se evalúa x > y para la instrucción if.

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

Un ejemplo cuando se usa sólo para evitar la necesidad de un bloque de

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

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

un uso sería en el golf código:

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

la primera línea es más corta, pero que se parece demasiado confuso para usar en el desarrollo normal

+3

... y quien escriba código así, pronto obtendrá lo que se merece. –

+0

Para enfatizar el efecto de la coma frente al punto y coma, su segunda línea probablemente debería usar un punto y coma entre y y z, como en '{y = 2; z = 3;}' – mskfisher

+0

@mskfisher: gracias por notarlo, me equivoqué segundo ejemplo – catwalk

5

El operador coma evalúa todos los operandos de izquierda a derecha, y el resultado es el valor del último operando.

Es principalmente útil en bucles for si desea realizar varias acciones en la parte "incremento", e.g (invirtiendo una cadena)

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

Otro ejemplo, donde podría ser una opción (la búsqueda de todas las ocurrencias de una cadena):

#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 particular, lógico y no se pueden utilizar para este condición, ya que tanto cero como distinto de cero pueden significar que el carácter se encontró en la cadena. Con la coma, por otro lado, se llama a position = s.find() cada vez que se evalúa la condición, pero el resultado de esta parte de la condición simplemente se ignora.

Naturalmente, hay otras maneras de escribir el bucle:

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

o simplemente

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

Como Frank mentioned, cómo se utiliza el operador coma en su ejemplo no causa un error. El operador coma puede ser confuso por varias razones:

  • no se ve muy a menudo, ya que sólo es necesario en algunas situaciones especiales
  • hay varios otros usos sintácticos de la coma que puede parecerse a un operador coma - pero que no son (las comas se utilizan para los parámetros de función/argumentos separados, las comas se utilizan para separar las declaraciones de variables o inicializadores)

Ya que es confuso ya menudo innecesario, el operador coma debe ser evitado a excepción de algunas situaciones muy específicas :

  • puede ser útil para realizar la operación múltiple en una o más de las expresiones de control de una declaración for
  • que se puede utilizar en las macros de preprocesador para evaluar más de una expresión en una sola sentencia. Esto generalmente se hace para permitir que las macros hagan más de una cosa y aún así sean una sola expresión, de modo que la macro se "ajuste" en lugares que solo permitan una expresión.

El operador de coma es un operador malintencionado, casi por definición, es para hackear 2 cosas donde solo se permite una. Casi siempre es feo, pero a veces eso es todo lo que tienes. Y esa es la única vez que debe usarlo; si tiene otra opción, no use el operador de coma.

En la parte superior de mi cabeza no puedo pensar en muchas otras razones para usar el operador, ya que puede obtener un efecto similar al evaluar las expresiones en declaraciones separadas en la mayoría de las otras situaciones (aunque estoy seguro alguien comentará sobre otro uso que he pasado por alto).

Cuestiones relacionadas