variable sirve significa que poner para operadores operador incremento ejemplos definicion decremento como aumentar c++ c compiler-construction post-increment

significa - para que sirve++ en c++



Comportamiento del operador de incremento de publicaciĆ³n (10)

C no garantiza el orden de evaluación de los parámetros en una llamada de función, por lo que con esto puede obtener los resultados "0 1" o "0 0". El orden puede cambiar de compilador a compilador, y el mismo compilador puede elegir diferentes órdenes según los parámetros de optimización.

Es más seguro escribir foo (test, test + 1) y luego hacer ++ test en la siguiente línea. De todos modos, el compilador debería optimizarlo si es posible.

Posible duplicado:
Comportamiento de operador de incremento previo y posterior en C, C ++, Java y C #

Aquí hay un caso de prueba:

void foo(int i, int j) { printf("%d %d", i, j); } ... test = 0; foo(test++, test);

Esperaría obtener una salida "0 1", pero obtengo "0 0" ¿Qué le da?


El orden de evaluación de los argumentos de una función no está definido. En este caso, parece que los hizo de derecha a izquierda.

(La modificación de variables entre puntos de secuencia básicamente permite a un compilador hacer lo que quiera).


Es posible que el compilador no esté evaluando los argumentos en el orden esperado.


Es un "comportamiento no especificado", pero en la práctica, con la forma en que se especifica la pila de llamadas C, casi siempre garantiza que la verá como 0, 0 y nunca 1, 0.

Como alguien señaló, la salida del ensamblador por VC empuja primero el parámetro más derecho en la pila. Así es como se implementan las llamadas de función C en ensamblador. Esto es para acomodar la característica de "lista de parámetros sin fin" de C. Al presionar los parámetros en un orden de derecha a izquierda, se garantiza que el primer parámetro será el elemento superior en la pila.

Tome la firma de printf:

int printf(const char *format, ...);

Esas elipsis denotan un número desconocido de parámetros. Si los parámetros se presionaron de izquierda a derecha, el formato estaría en la parte inferior de una pila de la cual no conocemos el tamaño.

Sabiendo que en C (y C ++) que los parámetros se procesan de izquierda a derecha, podemos determinar la forma más sencilla de analizar e interpretar una llamada de función. Llegue al final de la lista de parámetros y comience a presionar, evaluando cualquier declaración compleja a medida que avanza.

Sin embargo, incluso esto no puede salvarte, ya que la mayoría de los compiladores C tienen una opción para analizar las funciones "estilo Pascal". Y todo esto significa que los parámetros de la función se insertan en la pila de izquierda a derecha. Si, por ejemplo, printf se compiló con la opción Pascal, entonces la salida probablemente sería 1, 0 (sin embargo, dado que printf usa la elipse, no creo que se pueda compilar al estilo Pascal).


Um, ahora que el OP ha sido editado por coherencia, no está sincronizado con las respuestas. La respuesta fundamental sobre el orden de evaluación es correcta. Sin embargo, los valores posibles específicos son diferentes para el foo (prueba de ++, prueba); caso.

++ test se incrementará antes de pasar, por lo que el primer argumento siempre será 1. El segundo argumento será 0 o 1 según el orden de evaluación.


De acuerdo con el estándar C, es un comportamiento indefinido tener más de una referencia a una variable en un único punto de secuencia (aquí se puede considerar que es una declaración, o parámetros de una función) donde una de más de esas referencias incluye una modificación pre / post. Entonces: foo (f ++, f) <- indefinido en cuanto a cuando f se incrementa. Y del mismo modo (lo veo todo el tiempo en el código de usuario): * p = p ++ + p;

Normalmente, un compilador no cambiará su comportamiento para este tipo de cosas (a excepción de revisiones importantes).

Evítalo activando las advertencias y prestando atención a ellas.


¡Todo lo que dije originalmente es INCORRECTO! El punto en el tiempo en el que se calcula el efecto secundario no está especificado. Visual C ++ realizará el incremento después de la llamada a foo () si la prueba es una variable local, pero si la prueba se declara como estática o global, se incrementará antes de la llamada a foo () y producirá resultados diferentes, aunque el valor final de la prueba será correcta.

El incremento realmente debería hacerse en una declaración separada después de la llamada a foo (). Incluso si el comportamiento se especificara en el estándar C / C ++, sería confuso. Se podría pensar que los compiladores C ++ marcarían esto como un posible error.

Aquí hay una buena descripción de los puntos de secuencia y el comportamiento no especificado.

<---- COMIENZO DE INCORRECTO INCORRECTO INCORRECTO ---->

El bit "++" de "test ++" se ejecuta después de la llamada a foo. Entonces pasas (0,0) a foo, no (1,0)

Aquí está la salida del ensamblador de Visual Studio 2002:

mov ecx, DWORD PTR _i$[ebp] push ecx mov edx, DWORD PTR tv66[ebp] push edx call _foo add esp, 8 mov eax, DWORD PTR _i$[ebp] add eax, 1 mov DWORD PTR _i$[ebp], eax

El incremento se realiza DESPUÉS de la llamada a foo (). Si bien este comportamiento es por diseño, es ciertamente confuso para el lector casual y probablemente debería evitarse. El incremento realmente debería hacerse en una declaración separada después de la llamada a foo ()

<---- FIN DE INCORRECTO INCORRECTO INCORRECTO ---->


Para repetir lo que otros han dicho, este no es un comportamiento no especificado, sino indefinido. Este programa puede emitir legalmente cualquier cosa o nada, dejar n en cualquier valor o enviar correos electrónicos insultantes a su jefe.

Como una cuestión de práctica, los escritores de compiladores usualmente harán lo que es más fácil para ellos escribir, lo que generalmente significa que el programa buscará n una o dos veces, llamará a la función e incrementará en algún momento. Esto, como cualquier otro comportamiento concebible, está bien de acuerdo con el estándar. No hay ninguna razón para esperar el mismo comportamiento entre compiladores o versiones, o con diferentes opciones de compilación. No hay ninguna razón para que dos ejemplos diferentes pero similares en el mismo programa tengan que compilarse de manera consistente, aunque así es como apostaría.

En resumen, no hagas esto. Pruébelo bajo diferentes circunstancias si tiene curiosidad, pero no pretenda que hay un solo resultado correcto o incluso predecible.


Este es un ejemplo de comportamiento no especificado. La norma no indica en qué orden deben evaluarse los argumentos. Esta es una decisión de implementación del compilador. El compilador puede evaluar los argumentos de la función en cualquier orden.

En este caso, parece que en realidad procesa los argumentos de derecha a izquierda en lugar de los esperados de izquierda a derecha.

En general, hacer efectos secundarios en los argumentos es una mala práctica de programación.

En lugar de foo (prueba ++, prueba); deberías escribir foo (prueba, prueba + 1); prueba ++;

Sería semánticamente equivalente a lo que estás tratando de lograr.

Editar: Como Anthony señala correctamente, no está definido leer y modificar una sola variable sin un punto de secuencia intermedio. Entonces, en este caso, el comportamiento no está definido . Entonces el compilador es libre de generar el código que quiera.


Esto no es solo un comportamiento no especificado , en realidad es un comportamiento indefinido .

Sí, la evaluación del orden del argumento no está especificada , pero no está definido tanto para leer como para modificar una sola variable sin un punto de secuencia intermedio a menos que la lectura sea únicamente con el fin de calcular el nuevo valor. No existe un punto de secuencia entre las evaluaciones de los argumentos de la función, por lo que f(test,test++) es un comportamiento indefinido : la test se lee para un argumento y se modifica para el otro. Si mueve la modificación a una función, entonces está bien:

int preincrement(int* p) { return ++(*p); } int test; printf("%d %d/n",preincrement(&test),test);

Esto se debe a que hay un punto de secuencia en la entrada y salida al preincrement , por lo que la llamada debe evaluarse antes o después de la lectura simple. Ahora el orden no está especificado .

Tenga en cuenta también que el operador de coma proporciona un punto de secuencia, por lo que

int dummy; dummy=test++,test;

está bien --- el incremento ocurre antes de la lectura, por lo que el dummy se establece en el nuevo valor.