2010-12-09 22 views
5

Sé que C++ no especifica el orden en que se pasan los parámetros a una función. Pero si escribimos el siguiente código:orden de convocatoria y evaluación de llamadas

void __cdecl func(int a, int b, int c) 
{ 
     printf("%d,%d,%d", a,b,c); 
} 
int main() 
{ 
    int i=10; 
    func(++i, i, ++i); 
} 

Podemos decir de manera fiable la salida sería 12,11,11 ya que el __cdecl asegura que orden de los argumentos de paso es de derecha a izquierda?

+0

Como nunca escribiría un código como este, tengo curiosidad por saber qué provocó esta pregunta. ¿Cuál es la restricción? –

+0

http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points –

+0

Además, no ha leído el millón y una publicación acerca de no modificar una variable más de una vez en una declaración. –

Respuesta

12

según el estándar, hay dos cosas que hay que entender y diferenciar:

  1. C++ no especifica el orden en el que los parámetros son pasó a una función (como bien dice usted mismo, que es verdadero!)
  2. C++ no especifica el orden en que los argumentos de la función son evaluados [expr.call].

Ahora, tenga en cuenta, __cdecl asegura sólo la primera, no la segunda. Calling conventions decide solo cómo se pasarán los argumentos de las funciones, left-to-right o right-to-left; ¡aún se pueden evaluar en CUALQUIER orden!

Espero que esto aclare sus dudas con respecto a las convenciones de llamadas.

Sin embargo, dado que estas convenciones son la extensión del compilador de Microsoft a C++, su código no es portátil. En ese caso, puede ver cómo el compilador de MSVC++ evalúa los argumentos de la función y relajarse IF ¡no desea ejecutar el mismo código en otra plataforma!


func(++i, i, ++i); 

Tenga en cuenta que este código particular invoca un comportamiento indefinido, porque i se incrementa más de una vez sin cualquier intervenir cualquier punto de la secuencia.

+0

la convención de llamadas de bajo nivel no es lo mismo que el orden de evaluación de las expresiones. – seand

+0

No solo no es portátil entre plataformas, no es portátil entre compiladores diferentes en la misma plataforma, o incluso entre diferentes versiones del mismo compilador en la misma plataforma porque es ** comportamiento no definido **. –

+0

@ Adam ... sí, es cierto. – Nawaz

0

Está cambiando la misma variable más de una vez entre los puntos de secuencia (la evaluación del argumento de función es un punto de secuencia), lo que causa un comportamiento indefinido independientemente de la convención de llamada.

0

No, no puede suponer eso.
Un compilador de optimización integrará funciones cortas. Todo lo que __stdcall garantizará es que se generará la versión __stdcall de la función, pero esto no significa que el compilador tampoco pueda alinearla al mismo tiempo.
Si realmente quiere asegurarse de que no está en línea, tiene que declararlo en otra unidad de compilación, aunque las optimizaciones del enlazador podrían alinearse incluso en este caso.

Además, el orden de los parámetros en la pila no tiene nada que ver con el orden en que se evalúan.Por ejemplo, para una llamada a la función fn(a, b, c) GCC por lo general no hará

push c 
push b 
push a 
call fn 

sino

sub esp, 0xC 
mov [esp+8], c 
mov [esp+4], b 
mov [esp], a 
call fn 

Tenga en cuenta que en el segundo caso, no tiene restricciones en el orden.

0

Es posible que una determinada implementación de C defina lo que un compilador hará en ciertos casos que, según el estándar, sería un "comportamiento indefinido". Por ejemplo, establecer una variable int en ~ 0U constituiría un comportamiento indefinido, pero no hay nada en el estándar C que no permita a un compilador evaluar el int como -1 (o -493, para el caso). Tampoco hay nada que prohíba a un proveedor de compiladores en particular afirmar que su compilador en particular establecerá la variable en -1. Como __cdecl no está definido en el estándar C, y solo es aplicable a ciertos compiladores, la cuestión de cómo se define su semántica corresponde a esos proveedores; dado que el estándar C lo enumera como comportamiento no documentado, solo se documentará en la medida en que los proveedores particulares lo documenten.

Cuestiones relacionadas