2010-06-07 7 views
9

que tienen algo de código C:¿Orden de las operaciones para preincremento y postincremento en un argumento de función?

main() 
{ 
    int a=1; 
    void xyz(int,int); 

    xyz(++a,a++);  //which Unary Operator is executed first, ++a or a++? 

    printf("%d",a); 
} 
void xyz(int x,int y) 
{ 
    printf("\n%d %d",x,y); 
} 

La función xyz tiene dos parámetros pasados, ++a y a++. ¿Puede alguien explicar la secuencia de operaciones para explicar el resultado?

El código anterior imprime "3 13" o "2 23" dependiendo del compilador que se utilice.

+1

Probablemente sería más claro si utiliza diferentes variables en su programa de ejemplo. Además, debe poner "\ n" * después de * los valores que está imprimiendo, no antes. Esto imprimirá actualmente "2 23" – DevinB

+0

Debería intentar algo que sea más claro. Esa sintaxis es bastante extraña para un ser humano. Haga el código simple, no intente escribir cosas complicadas. – INS

Respuesta

26

Bueno, hay dos cosas a tener en cuenta con su código de ejemplo:

  1. El orden de evaluación de argumentos de la función no está especificado, por lo que si ++a o a++ se evalúa primero es dependiente de la implementación.
  2. Modificando el valor de a más de una vez sin un punto de secuencia entre las modificaciones da como resultado un comportamiento indefinido. Por lo tanto, los resultados de su código no están definidos.

Si simplificamos su código y quite el comportamiento indeterminado e indefinido, entonces podemos responder a la pregunta:

void xyz(int x) { } 

int a = 1; 
xyz(a++); // 1 is passed to xyz, then a is incremented to be 2 

int a = 1; 
xyz(++a); // a is incremented to be 2, then that 2 is passed to xyz 
+0

¿Es cierto en el segundo caso que 'a' se actualiza antes de llamar a la función? Sé que el resultado de la * expresión * '++ a' es 2, que es lo que se pasa a' xyz', pero mi entendimiento es que el efecto secundario no necesariamente se aplicará antes de que se llame a la función. –

+2

@John: Sí: hay un punto de secuencia después de la evaluación de todos los argumentos de una función, pero antes de llamar a la función. –

9

Citando Kernighan & Ritchie, Capítulo 2.12:

El orden en el que función argumentos se evalúan no se especifica, por lo que la declaración

printf("%d %d\n", ++n, power(2, n)); /* WRONG */ 

puede producir resultados diferentes con compiladores diferentes, según si n se incrementa antes de que se llame al . La solución, por supuesto, es escribir

++n; 
printf("%d %d\n", n, power(2, n)); 

llamadas de función, la asignación anidada declaraciones, y de incremento y operadores decremento causa `` laterales efectos '' - alguna variable se cambia como un subproducto de la evaluación de una expresión. En cualquier expresión que implique efectos secundarios, puede haber dependencias sutiles en el orden en cuyas variables que forman parte de la expresión se actualizan. Una infeliz situación se caracteriza por la declaración

a[i] = i++; 

La pregunta es si el subíndice es el antiguo valor de i o el nuevo. Los compiladores pueden interpretar esto en de diferentes maneras y generar diferentes respuestas según su interpretación . La norma deja intencionalmente la mayoría de tales asuntos no especificados. Cuando los efectos secundarios (asignación a variables) tienen lugar dentro de una expresión se deja a la discreción del compilador, ya que el mejor orden depende en gran medida de la arquitectura de la máquina .(La norma especifica que todos los efectos secundarios sobre argumentos entran en vigor antes de una función se llama, pero eso no sería ayuda en la llamada a printf arriba.) La moral es que escribir código que depende del orden de evaluación es una mala práctica de programación en cualquier lenguaje . Naturalmente, es necesario para saber qué cosas evitar, pero si no sabe cómo se hacen en varias máquinas, no tendrá la tentación de para aprovechar una implementación particular de .

2

Unario secuencia de evaluación del operador para una función:

#include <stdio.h> 

void xyz(int x, int y) { 
    printf("x:%d y:%d ", x, y); 
} 

main() { 
    int a; 
    a=1; xyz(++a, a);  printf("a:%d\n", a); 
    a=1; xyz(a, a++);  printf("a:%d\n", a); 
    a=1; xyz(++a, a++);  printf("a:%d\n", a); 
} 

es la salida

x:2 y:2 a:2 
x:2 y:1 a:2 
x:3 y:1 a:3 

En mi sistema. Esto indica que el segundo parámetro de la función se está evaluando primero. No debe confiar en el orden de evaluación de los parámetros de la función. No está definido, por lo que será diferente en diferentes sistemas.

Sin embargo, hay un buen trabajo para encontrar un buen ejemplo de este comportamiento.

-1

Para operadores unitarios, existe el preincremento (++ i) y el incremento posterior (i ++). Para el preincremento, el valor que se incrementará se agregará antes de una operación. Por ejemplo:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << ++i; 
} 

En este caso, la salida sería 1. La variable 'i' se incrementó por el valor de 1 antes de cualquier otra operación, es decir 'cout < < ++ i'.

Ahora, si hicimos el post-incremento en la misma función:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << i++; 
} 

La salida sólo sería 0. Esto se debe a que el incremento ocurriría después de la operación. Pero ya que usted quiere saber acerca de pasarlos en como parámetros, esto es lo que pasará:

#include <iostream> 
using namespace std; 
// Function Prototypes 
void PrintNumbers(int, int); 

void main() 
{ 
    int a = 0, b = 0; 
    PrintNumbers(++a, b++); 
} 

void PrintNumbers(int a, int b) 
{ 
    cout << "First number: " << a << endl; 
    cout << "Second number: " << b << endl; 
} 

Al pasar en aquellas variables como parámetros, la salida sería:

First number: 1 
Second number: 0 

espero que este ayuda !!

Cuestiones relacionadas