¿Los compiladores aprovechan la secuencia indeterminada de los argumentos de las funciones?

Resuelto RaptorFactor asked hace 15 años • 7 respuestas

Bien, soy consciente de que el estándar dicta que una implementación de C++ puede elegir en qué orden se evalúan los argumentos de una función, pero ¿hay alguna implementación que realmente "aproveche" esto en un escenario en el que realmente afectaría al programa?

Ejemplo clásico:

int i = 0;
foo(i++, i++);

Nota: No busco que alguien me diga que no se puede confiar en el orden de evaluación, lo sé muy bien. Solo me interesa saber si algún compilador realmente evalúa de izquierda a derecha porque supongo que si lo hiciera, muchos códigos mal escritos se romperían (con razón, pero aún así probablemente se quejarían).

RaptorFactor avatar Mar 07 '09 15:03 RaptorFactor
Aceptado

Depende del tipo de argumento, la convención de llamada de la función llamada, la arquitectura y el compilador. En un x86, la convención de llamada de Pascal evalúa los argumentos de izquierda a derecha, mientras que en la convención de llamada de C ( __cdecl ) es de derecha a izquierda. La mayoría de los programas que se ejecutan en múltiples plataformas tienen en cuenta las convenciones de llamadas para evitar sorpresas.

Hay un buen artículo en el blog de Raymond Chen si está interesado. Quizás también quieras echar un vistazo a la sección Pila y llamadas del manual de GCC.

Editar: Siempre y cuando estemos dividiendo los pelos: mi respuesta trata esto no como una pregunta de idioma sino como una pregunta de plataforma. El estándar del idioma no garantiza ni prefiere uno sobre el otro y lo deja sin especificar . Tenga en cuenta la redacción. No dice que esto no esté definido. En este sentido, no especificado significa algo con lo que no se puede contar, un comportamiento no portátil. No tengo la especificación/borrador de C a mano, pero debería ser similar al de mi borrador n2798 (C++)

Algunos otros aspectos y operaciones de la máquina abstracta se describen en esta norma internacional como no especificados (por ejemplo, orden de evaluación de los argumentos de una función). Cuando sea posible, esta Norma Internacional define un conjunto de comportamientos permitidos. Estos definen los aspectos no deterministas de la máquina abstracta. Por tanto, una instancia de la máquina abstracta puede tener más de una secuencia de ejecución posible para un programa determinado y una entrada determinada.

dirkgently avatar Mar 07 '2009 08:03 dirkgently

Encontré la respuesta en los estándares de C++ .

Párrafo 5.2.2.8:

El orden de evaluación de los argumentos no se especifica. Todos los efectos secundarios de las evaluaciones de expresiones de argumentos entran en vigor antes de ingresar a la función. El orden de evaluación de la expresión de sufijo y la lista de expresiones de argumento no está especificado.

En otras palabras, depende únicamente del compilador.

Igor avatar Jan 09 '2012 08:01 Igor

Lee esto

No es una copia exacta de su pregunta, pero mi respuesta (y algunas otras) también cubren su pregunta.

Hay muy buenas razones de optimización por las que el compilador podría no sólo elegir de derecha a izquierda sino también intercalarlos.

La norma ni siquiera garantiza un orden secuencial. Solo garantiza que cuando se llama a la función, todos los argumentos se hayan evaluado completamente.

Y sí, he visto algunas versiones de GCC hacer exactamente esto. Para su ejemplo, se llamaría foo(0,0) y luego yo sería 2. (No puedo darle el número de versión exacto del compilador. Fue hace un tiempo, pero no me sorprendería ver que este comportamiento vuelva a aparecer. Es una forma eficaz de programar instrucciones)

jalf avatar Mar 07 '2009 10:03 jalf