¿Por qué la expresión a = a + b – (b = a) da una advertencia de punto de secuencia en c ++?

A continuación está el código de prueba:

int main() { int a = 3; int b = 4; a = a + b - (b = a); cout << "a :" << a << " " << "b :" << b << "\n"; return 0; } 

Comstackr esto da la siguiente advertencia:

 > $ g++ -Wall -o test test.cpp test.cpp: In function 'int main()': > test.cpp:11:21: warning: operation on 'b' may be undefined > [-Wsequence-point] 

¿Por qué la operación puede ser indefinida?

De acuerdo con mi entendimiento, primero la subexpresión (b = a) debería evaluarse debido a la mayor precedencia de (), estableciendo así b = a. Entonces, dado que ‘+’ y ‘-‘ tienen la misma precedencia, la expresión se evaluaría a la izquierda de forma asociativa. Por lo tanto, a + b debería evaluarse a continuación, y finalmente el resultado de (b = a) debe restarse de a + b . No puedo ver ninguna regla de punto de secuencia violada aquí.

Existe una diferencia entre una expresión que se evalúa y que completa sus efectos secundarios .

La expresión de asignación b = a se evaluará antes de la resta debido a la mayor precedencia de los paréntesis. Proporcionará el valor de a como resultado de la evaluación. La escritura de ese valor en b , sin embargo, puede no completarse hasta el siguiente punto de secuencia, que en este caso es el final de la expresión completa. El resultado final de la expresión general no está definido, porque la resta puede tomar el valor de b antes o después de la asignación.

En C ++, las subexpresiones en expresiones aritméticas no tienen orden temporal.

 a = x + y; 

¿Se evalúa x primero, o y ? El comstackdor puede elegir cualquiera, o puede elegir algo completamente diferente. El orden de evaluación no es lo mismo que la precedencia del operador: la precedencia del operador está estrictamente definida, y el orden de evaluación solo se define por la granularidad de que su progtwig tenga puntos de secuencia.

De hecho, en algunas architectures es posible emitir código que evalúa tanto x como y al mismo tiempo, por ejemplo, architectures VLIW.

Para resolverlo, sepáralos en dos declaraciones diferentes.

PD: No olvides que los humanos pueden cometer errores al realizar operaciones aritméticas. Por lo tanto, es mejor aclarar las operaciones separándolas en diferentes declaraciones. Espero haber ayudado.

 int main() { int a = 3; int b = 4; /* Two different Statements*/ b = a; /* or a = a + b - a */ a = a + b - b; cout<<"a :"< 

a = b + a - a; se acaba de escribir como

a = b + a - (b = a) —— >> (exp 1)

Los siguientes tres resultados son los mismos que (exp 1) a = (b + a - (b = a)); a = ((b + a) - (b = a)); a = (b + a) - (b = a);

Observaciones +, – los operadores tienen la misma precedencia y asociatividad de izquierda a derecha. Por lo tanto, ‘b + a’ se ejecuta primero y luego ‘a’ se asigna a ‘b’ antes de la resta

Ahora observe lo siguiente cuando a = 10 yb = 20;

a = (b = a) - b + a; =======> a = 10; b = 10 a = ((b = a) - b + a); =======> a = 10; b = 10

a = ((b = a) - (b + a)); =======> a = -10; b = 10 De las expresiones anteriores, está claro que incluso si se ejecuta el paréntesis más interior primero se sigue primero la asociatividad y luego la precedencia

Nota: Para evitar confusiones entre la precedencia del paréntesis externo e interno, considere la siguiente expresión a = (b + a - (b = a)) =====> Resultado real => a = 20, b = 10; habría sido a = 10, b = 10; (si la precedencia es primaria en comparación con la asociatividad) Por lo tanto, en el ejemplo anterior podemos decir que la asociatividad es primaria en comparación con la precedencia