2010-10-02 11 views
7
inversa

Aquí está mi función:argumentos de la función de paso en

void abc(char *def, unsigned int w, unsigned int x, unsigned int y, unsigned int z) 
{ 
    printf("val 1 : %d\n", w); 
    printf("val 2 : %d\n", x); 
    printf("val 3 : %d\n", y); 
    printf("val 4 : %d\n", z); 
} 

y aquí es donde yo llamo esta función:

unsigned int exp[4] = { 1, 2, 3, 4 }; 
unsigned short count = 0; 
abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]); 

y aquí está la salida que espero:

val1 : 1 
val2 : 2 
val3 : 3 
val4 : 4 

pero lo que se ve es completamente inversa de la misma:

val1 : 4 
val2 : 3 
val3 : 2 
val4 : 1 

No sé por qué? Cualquier ayuda sería apreciada.

+0

Su printf también está roto, se come el primer espacio en la cadena de formato! :) –

Respuesta

8

De docs estándar, 5,4

Excepto donde se indique, el orden de evaluación de los operandos de los operadores y subexpresiones de expresiones individuales, y el orden en que los efectos secundarios tienen lugar individuales, es unspecified58) Entre el punto de secuencia anterior y siguiente, un objeto escalar tendrá su valor almacenado modificado como máximo una vez por la evaluación de una expresión. Además, se debe acceder al valor anterior solo para determinar el valor que se almacenará.Los requisitos de este párrafo se cumplirán para cada orden permitida de las subexpresiones de una expresión completa; de lo contrario, el comportamiento no está definido.

Un ejemplo de la propia documentación estándar,

i = v[i ++];// the behavior is undefined

Y es por la misma razón que

abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]); no está definido ..

-4

Esto es debido a la convención de llamada. En _cdecl, la convención de llamada predeterminada para los programas c/C++ (según microsoft), los parámetros se pasan en la pila a la función en orden inverso. Debido a esto, los parámetros también se evalúan en orden inverso.

+4

Eso no es del todo cierto. No hay nada en el estándar que diga que los argumentos se pasan a la pila de derecha a izquierda (por ej .: la forma en que lo hace gcc). De hecho, nada dice que tiene que haber una pila en absoluto. – NullUserException

+0

Estoy escribiendo mi programa en 64 bit arch. así que supongo que los parámetros de configuración se almacenarán en los registros. –

+0

Sí, pero estoy hablando de la convención de llamadas que utiliza este compilador en particular, que parece ser el más común. –

2

Ha invocado el comportamiento indefinido, modificando count más de una vez sin una intervención sequence point.

4

No use el operador ++, que operan en la misma variable, más de una vez en el mismo comunicado. El orden en que se realizará la operación no está definido.

Probar:

abc(anyarray, exp[count], exp[count+1], exp[count+2], exp[count+3]); 
count += 4; 
+1

'No deberías usar el operador ++ más de una vez en la misma frase" ¿Por qué no? 'c = a ++ + b ++' está bien definido. –

+2

@Prasoon: OK, editado para abordar este punto. Pero los múltiples usos de los operadores de incremento conducen al tipo de problema en la pregunta original. Yo escribiría c = a + b; a ++; b ++; yo mismo – Andrew

1

Usted está contando con los parámetros está siendo evaluada, de izquierda a derecha. No puede hacer suposiciones sobre el orden en que se evalúan. En este caso, parece que el compilador los está evaluando de derecha a izquierda.

Además, es posible que desee para buscar puntos de secuencia, ya que puede ser que no se debe utilizar el operador ++ de esta manera.

+0

No hay "mayo" al respecto. El estándar nombra esto como ** comportamiento indefinido **, lo que significa que el compilador puede hacer cualquier cosa, incluso para causar demonios nasales. – greyfade

+0

Sí, pero irónicamente también significa que puede funcionar del modo que usted espera. Tienes razón, por supuesto, la "posibilidad" es que yo evite ser demasiado preceptivo en una respuesta, aunque, en este caso, un poco de preceptividad es probablemente apropiado. – jwismar

1

abc(anyarray, exp[count++], exp[count++], exp[count++], exp[count++]);

El orden de evaluación de los argumentos de abc es no especificado pero la expresión invoca un comportamiento indefinido ya que están tratando de modificar una variable count más de una vez entre dos puntos de secuencia.

Por otra parte el uso de especificador de formato incorrecto en printf() invoca también UB. Asegúrese de haber utilizado los especificadores de formato correctos (es decir, %u para unsigned int) en printf().

+1

Sería posible obtener todos los valores 1, o todos los valores 4 también. –

+0

Creo que es importante tener en cuenta que 'count' es una variable escalar y, por lo tanto, es UB. Esto no es un problema si 'cuenta' si de UDT – Chubsdad

0

lo que tienes Esto porque llamado adb(exp,a,b,c,d) según su problema, pero durante la llamada de la función d se empuja primero en la pila y luego c ,b relativamente. Al pasar el exp[count++] en el último argumento que procesará primero para pasar por encima de la pila, significa que primero se empuja 1, luego 2, luego 3 y 4. Y en la llamada llamada pop realizada se obtiene w=4 x=3 y=2 z=1 eso es todo.

Cuestiones relacionadas