loop - operadores de asignacion en c++
¿Cómo funciona el operador de coma? (9)
El operador de coma tiene la precedencia más baja de todos los operadores de C / C ++. Por lo tanto, siempre es el último en unirse a una expresión, lo que significa esto:
a = b, c;
es equivalente a:
(a = b), c;
Otro hecho interesante es que el operador de coma introduce un punto de secuencia . Esto significa que la expresión:
a+b, c(), d
se garantiza que tiene sus tres subexpresiones ( a + b , c () yd ) evaluadas en orden. Esto es significativo si tienen efectos secundarios. Normalmente los compiladores pueden evaluar subexpresiones en el orden que consideren adecuado; por ejemplo, en una llamada a función:
someFunc(arg1, arg2, arg3)
los argumentos se pueden evaluar en un orden arbitrario. Tenga en cuenta que las comas en la llamada a la función no son operadores; ellos son separadores
¿Cómo funciona el operador de coma en C ++?
Por ejemplo, si lo hago:
a = b, c;
¿Un final iguala b o c?
(Sí, sé que esto es fácil de probar, solo documentar aquí para que alguien encuentre la respuesta rápidamente).
Actualización: esta pregunta ha expuesto un matiz al usar el operador de coma. Solo para documentar esto:
a = b, c; // a is set to the value of b!
a = (b, c); // a is set to the value of c!
Esta pregunta fue inspirada por un error tipográfico en el código. Lo que se pretendía ser
a = b;
c = d;
Convertido en
a = b, // <- Note comma typo!
c = d;
El operador de coma:
- tiene la precedencia más baja
- es de izquierda asociativo
Se define una versión predeterminada del operador de coma para todos los tipos (integrado y personalizado), y funciona de la siguiente manera: exprA , exprB
dado exprA , exprB
:
-
exprA
es evaluado - el resultado de
exprA
es ignorado -
exprB
es evaluado - el resultado de
exprB
se devuelve como resultado de la expresión completa
Con la mayoría de los operadores, el compilador puede elegir el orden de ejecución e incluso se requiere omitir la ejecución en absoluto si no afecta el resultado final (por ejemplo, false && foo()
omitirá la llamada a foo
). Sin embargo, este no es el caso para el operador de coma y los pasos anteriores siempre ocurrirán * .
En la práctica, el operador de coma predeterminado funciona casi de la misma manera que un punto y coma. La diferencia es que dos expresiones separadas por un punto y coma forman dos instrucciones separadas, mientras que la separación de coma mantiene todo como una sola expresión. Esta es la razón por la que el operador de coma a veces se usa en los siguientes escenarios:
- La sintaxis de C requiere una única expresión , no una declaración. por ejemplo, en
if( HERE )
- La sintaxis C requiere una sola instrucción, no más, por ejemplo, en la inicialización del bucle
for ( HERE ; ; )
- Cuando quiera saltear llaves y mantener una sola declaración:
if (foo) HERE ;
(Por favor, no hagas eso, ¡es realmente feo!)
Cuando una declaración no es una expresión, el punto y coma no puede ser reemplazado por una coma. Por ejemplo, estos no están permitidos:
-
(foo, if (foo) bar)
(if
no es una expresión) - int x, int y (declaración de variable no es una expresión)
En tu caso tenemos:
-
a=b, c;
, equivalente aa=b; c;
a=b; c;
, suponiendo quea
es de tipo que no sobrecarga al operador de coma. -
a = b, c = d;
equivalente aa=b; c=d;
a=b; c=d;
, suponiendo quea
es de tipo que no sobrecarga al operador de coma.
Tenga en cuenta que no todas las comas son en realidad un operador de coma. Algunas comas que tienen un significado completamente diferente:
-
int a, b;
--- la lista de declaraciones de variables está separada por comas, pero estos no son operadores de coma -
int a=5, b=3;
--- esta es también una lista de declaraciones de variables separadas por comas -
foo(x,y)
--- lista de argumentos separados por comas. De hecho,x
ey
se pueden evaluar en cualquier orden. -
FOO(x,y)
--- lista de macro argumentos separados por comas -
foo<a,b>
--- lista de argumentos de plantilla separados por comas -
int foo(int a, int b)
--- lista de parámetros separados por comas -
Foo::Foo() : a(5), b(3) {}
--- lista de inicializadores separados por comas en un constructor de clase
* Esto no es del todo cierto si aplica optimizaciones. Si el compilador reconoce que cierto fragmento de código no tiene ningún impacto en el resto, eliminará las declaraciones innecesarias.
Lectura adicional: http://en.wikipedia.org/wiki/Comma_operator
El valor de a
será b
, pero el valor de la expresión será c
. Es decir, en
d = (a = b, c);
a sería igual a b
, d
sería igual a c
.
El valor de a será igual a b, ya que el operador de coma tiene una prioridad menor que el operador de asignación.
El valor de b se asignará a a. No pasará nada a c
Sí, el operador de Coma tiene baja prioridad que el operador de Asignación
#include<stdio.h>
int main()
{
int i;
i = (1,2,3);
printf("i:%d/n",i);
return 0;
}
Salida: i = 3
Porque el operador de coma siempre devuelve el valor más a la derecha.
En el caso de operador de coma con operador de asignación:
int main()
{
int i;
i = 1,2,3;
printf("i:%d/n",i);
return 0;
}
Ouput: i = 1
Como sabemos, el operador de coma tiene una prioridad menor que la asignación .....
Sería igual a b
.
El operador de coma tiene una prioridad menor que la asignación.
Tenga cuidado de observar que el operador de coma puede estar sobrecargado en C ++. El comportamiento real puede ser muy diferente de lo esperado.
Como ejemplo, Boost.Spirit utiliza el operador de coma bastante hábilmente para implementar inicializadores de listas para tablas de símbolos. Por lo tanto, hace que la siguiente sintaxis sea posible y significativa:
keywords = "and", "or", "not", "xor";
Tenga en cuenta que debido a la precedencia del operador, el código es (¡intencionadamente!) Idéntico a
(((keywords = "and"), "or"), "not"), "xor";
Es decir, el primer operador llamado es keywords.operator =("and")
que devuelve un objeto proxy en el que se invocan los operator,
restantes:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
Lo primero es lo primero: Comma en realidad no es un operador, para el compilador es solo un token que tiene un significado en contexto con otros tokens.
¿Qué significa esto y por qué molestarse?
Ejemplo 1:
Para entender la diferencia entre el significado del mismo token en un contexto diferente, echamos un vistazo a este ejemplo:
class Example {
Foo<int, char*> ContentA;
}
Por lo general, un principiante en C ++ pensaría que esta expresión podría / compararía cosas, pero es absolutamente errónea, el significado de los signos <
, >
y ,
tokens depende del contexto de uso.
La interpretación correcta del ejemplo anterior es, por supuesto, que es una instalación de una plantilla.
Ejemplo 2:
Cuando escribimos un bucle típicamente para con más de una variable de inicialización y / o más de una expresión que se debe hacer después de cada iteración del bucle, también usamos la coma:
for(a=5,b=0;a<42;a++,b--)
...
El significado de la coma depende del contexto de uso, aquí está el contexto de la construcción.
¿Qué significa realmente una coma en contexto?
Para complicarlo aún más (como siempre en C ++), el operador de coma puede estar sobrecargado (gracias a por señalarlo).
Para volver a la pregunta, el Código
a = b, c;
significa para el compilador algo así como
(a = b), c;
porque la priority de =
token / operator es mayor que la prioridad de token.
y esto se interpreta en contexto como
a = b;
c;
(tenga en cuenta que la interpretación depende del contexto, aquí no es ni una función / llamada de método o una plantilla de instatción.)