valor - tipos de parametros en c++
Compiladores y orden de evaluaciĆ³n de argumento en C++ (6)
Depende del tipo de argumento, la convención de llamadas de la función llamada, la arquitectura y el compilador. En un x86, la convención de llamadas Pascal evalúa los argumentos de izquierda a derecha, mientras que en la convención de llamadas 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 saltarse sorpresas.
Hay un buen article en el blog de Raymond Chen si está interesado. También puede consultar la sección Pila y llamadas del manual de GCC.
Editar: Mientras sepamos pelos: mi respuesta trata esto no como una cuestión de idioma sino como una plataforma. El estándar de idioma no garantiza o prefiere uno sobre el otro y lo deja como no especificado . Tenga en cuenta la redacción. No dice que esto no está definido. Sin especificar en este sentido significa algo con lo que no puede contar, el comportamiento no portátil. No tengo a mano la especificación C / borrador, pero debería ser similar a la 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 argumentos para una función). Donde sea posible, este Estándar Internacional define un conjunto de comportamientos permitidos. Estos definen los aspectos no deterministas de la máquina abstracta. Una instancia de la máquina abstracta puede así tener más de una secuencia de ejecución posible para un programa dado y una entrada dada.
De acuerdo, soy consciente de que el estándar dicta que una implementación en C ++ puede elegir en qué orden se evalúan los argumentos de una función, pero ¿hay implementaciones que realmente "aprovechen" esto en un escenario donde realmente afectaría el programa?
Ejemplo clásico:
int i = 0;
foo(i++, i++);
Nota: No estoy buscando a alguien que me diga que no se puede confiar en el orden de la evaluación, lo sé muy bien. Solo me interesa saber si algún compilador realmente evalúa de una orden de izquierda a derecha porque supongo que si lo hicieran se romperían muchos códigos mal escritos (con razón, pero probablemente se quejarían).
Encontré respuesta en estándares de C ++ .
Párrafo 5.2.2.8:
El orden de evaluación de los argumentos no está especificado. Todos los efectos secundarios de las evaluaciones de expresión de argumentos surten efecto antes de que se ingrese la función. El orden de evaluación de la expresión de postfijo y la lista de expresión de argumento no está especificado.
En otras palabras, depende del compilador solamente.
Espero que la mayoría de los compiladores modernos intenten intercalar las instrucciones de cálculo de los argumentos, dado que el estándar de C ++ exige que sean independientes y, por lo tanto, carecen de interdependencias. Hacer esto debería ayudar a mantener llenas las unidades de ejecución de una CPU profundamente canalizada y por lo tanto aumentar el rendimiento. (Al menos esperaría que un compilador que dice ser un compilador optimizador lo haga cuando se dan indicadores de optimización).
La última vez que vi diferencias fue entre VS2005 y GCC 3.x en un hardware x86 en 2007. Así que es (¿era?) Una situación muy probable. Así que nunca confío más en la orden de evaluación. Tal vez es mejor ahora.
Todos los argumentos son evaluados. Orden no definida (según el estándar). Pero todas las implementaciones de C / C ++ (que yo sepa) evalúan los argumentos de la función de derecha a izquierda . EDITAR: CLang es una excepción (ver comentario a continuación).
Creo que la orden de evaluación de derecha a izquierda ha sido muy antigua (desde los primeros compiladores de C). Ciertamente, mucho antes de que se inventara C ++, y la mayoría de las implementaciones de C ++ mantendrían el mismo orden de evaluación porque las primeras implementaciones de C ++ simplemente se tradujeron en C.
Hay algunos motivos técnicos para evaluar los argumentos de la función de derecha a izquierda. En las arquitecturas de pila, los argumentos generalmente se insertan en la pila. En C / C ++, puede llamar a una función con más argumentos de los que realmente se especificaron: los argumentos adicionales se ignoran simplemente. Si los argumentos se evalúan de izquierda a derecha y se presionan de izquierda a derecha, la ranura de la pila justo debajo del puntero de la pila contendrá el último argumento, y no hay forma de que la función obtenga el desplazamiento de un argumento en particular (porque la cantidad real de argumentos empujados depende de la persona que llama).
En una orden de inserción de derecha a izquierda, la ranura de la pila justo debajo del puntero de la pila siempre mantendrá el primer argumento, y la siguiente ranura contendrá el segundo argumento, etc. Las compensaciones de los argumentos siempre serán determinísticas para la función (que pueden escribirse y compilado en otro lugar en una biblioteca, por separado de donde se lo llama).
Ahora, el orden de inserción de derecha a izquierda no ordena el orden de evaluación de derecha a izquierda, pero en los primeros compiladores, la memoria es escasa. En el orden de evaluación de derecha a izquierda, la misma pila se puede utilizar en el lugar (esencialmente, después de evaluar el argumento, que puede ser una expresión o una llamada de función), el valor de retorno ya está en la posición correcta en el apilar). En la evaluación de izquierda a derecha, los valores del argumento se deben almacenar por separado y se deben volver a la pila en orden inverso.
No es una copia exacta de su pregunta, pero mi respuesta (y algunas otras) también cubre su pregunta.
Hay muy buenas razones de optimización por las que el compilador podría no solo elegir de derecha a izquierda sino también intercalarlas.
El estándar ni siquiera garantiza un orden secuencial. Solo garantiza que cuando se llame a la función, todos los argumentos se hayan evaluado por completo.
Y sí, he visto algunas versiones de GCC hacer exactamente esto. Para su ejemplo, se llamaría foo (0,0) y yo sería 2 después. (No puedo darte el número de versión exacto del compilador. Fue hace un tiempo, pero no me sorprendería ver que este comportamiento aparece de nuevo. Es una forma eficiente de programar instrucciones)