2012-03-05 23 views
17

En C/C++, ¿hay un orden fijo para la evaluación del parámetro de la función? Quiero decir, ¿qué dicen los estándares? ¿Es left-to-right o right-to-left? Estoy recibiendo información confusa de los libros.orden de evaluación del parámetro de función

Es necesario que function call se implemente usando stack only. ¿Qué dicen los estándares C/C++ sobre esto?

+6

Las normas no especifican la misma. El orden podría incluso cambiar aleatoriamente en el tiempo de ejecución (pero ninguna implementación lo hace, AFAIK). –

+3

Nota pequeña: podría pensar que una coma es un punto de secuencia, lo que obligaría a ordenar de izquierda a derecha. Pero el operador de coma es un punto de secuencia, no la coma que separa los parámetros de función. – ugoren

+0

Si confía en él, entonces su código puede ser difícil de leer, razonar y mantener. –

Respuesta

29

C y C++ son dos idiomas completamente diferentes; no suponga que las mismas reglas se aplican siempre a ambos. En el caso de la orden de evaluación de parámetros, sin embargo:

C99:

6.5.2.2 función llama
...
10 El orden de evaluación del designador de función, los argumentos reales, y subexpresiones dentro de los argumentos reales no especificadas, pero hay un punto de secuencia antes de la llamada real.

[Editar ] C11 (borrador):

6.5.2.2 función llama
...
10 Hay un punto de secuencia después de las evaluaciones de la función y el designador argumentos reales pero antes de la llamada real. Cada evaluación en la función de llamada (incluyendo otras llamadas a función) que no está secuenciada específicamente antes o después de la ejecución del cuerpo de la función llamada se secuencia indeterminadamente con respecto a la ejecución de la función llamada. 94)
...
94) En otras palabras, las ejecuciones de funciones no se "entrelazan" entre sí.

C++:

5.2.2 Función llamada
...
8 El orden de evaluación de argumentos no se especifica. Todos los efectos secundarios de las evaluaciones de expresión de argumentos tienen 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 es no especificado.

Ninguno de los dos mandatos exige el uso de la pila de hardware para pasar parámetros de funciones; eso es un detalle de implementación. El estándar de C++ usa el término "desenrollar la pila" para describir los destructores de llamada para objetos creados automáticamente en la ruta desde un bloque try a una throw-expression, pero eso es todo. Las arquitecturas más populares hacen pasan parámetros a través de una pila de hardware, pero no es universal.

[Editar ]

estoy recibiendo información confusa de los libros.

Esto no es en absoluto sorprendente, ya que fácilmente el 90% de los libros escritos sobre C son simplemente basura .

Si bien el estándar de idioma no es un gran recurso para aprendiendo C o C++, es bueno tenerlo a mano para preguntas como esta. Los documentos oficiales de las normas ™ cuestan dinero real, pero hay borradores que están disponibles gratuitamente en línea y deberían ser lo suficientemente buenos para la mayoría de los propósitos.

El último borrador C99 (con actualizaciones desde la publicación original) está disponible here. El último borrador C11 previo a la publicación (que fue oficialmente ratificado el año pasado) está disponible here. Y un borrador disponible públicamente del lenguaje C++ está disponible here, aunque tiene un descargo de responsabilidad explícito de que parte de la información está incompleta o es incorrecta.

+0

"El estándar C++ usa el término" desenrollar la pila "- Estoy de acuerdo contigo, y creo que" desenrollar la pila "se refiere a retroceder a través de la * pila de llamadas *, que conceptualmente es una pila independientemente de cómo esté realmente representada en memoria, y también independientemente de cómo se relacionan las direcciones de los parámetros de función con cualquier estructura que la implementación pueda usar para representar la pila de llamadas. Por lo tanto, el término "desenrollar la pila" no perjudica la convención de llamadas, y de hecho muchas convenciones al menos algunos registros donde sea posible. –

+4

_since fácilmente el 90% de los libros escritos _... ¿Sabías también que el 95% de las declaraciones que usan estadísticas para afirmar su verdad se inventan en el acto, y son completamente inútiles salvo para caracterizar otras estadísticas ? (buena respuesta por cierto) – ryyker

+0

@John Bode "C y C++ son dos idiomas completamente diferentes; no suponga que las mismas reglas se aplican siempre a ambos. " Los compiladores de C++ compilan códigos C, por lo que podemos decir que las reglas de C son aptas para C++, ¿no? –

6

Manteniéndolo a salvo: la norma deja en manos del compilador determinar el orden en que se evalúan los argumentos. Por lo tanto, no debe confiar en que se mantenga un orden específico.

+1

Te recomendaría si eliminaste el segundo párrafo. Solo creo que eso confunde las cosas. –

+0

@sad: no se puede "evitar" nada. No vuelva a quejarse cuando el compilador optimizó su código para hacer las cosas mal, porque se basó en suposiciones poco confiables. –

+3

El segundo párrafo es simplemente incorrecto. Incluso si la convención de llamadas es presionar los parámetros en orden de derecha a izquierda, el reordenamiento de instrucciones puede cambiar el orden de evaluación. – interjay

2

En C/C++ hay un orden fijo para la evaluación del parámetro de la función. Me refiero a lo que dicen las normas es de izquierda a derecha o de derecha a izquierda. Estoy obteniendo información confusa de los libros.

No, el orden de evaluación de parámetros de la función (y de dos sub-expresiones en cualquier expresión) es comportamiento no especificado en C y C++. En inglés simple eso significa que el parámetro de la izquierda se pudo evaluar primero, o podría ser el más correcto, y no se puede saber qué orden se aplica a un compilador en particular.

Ejemplo:

static int x = 0; 

int* func (int val) 
{ 
    x = val; 
    return &x; 
} 

void print (int val1, int val2) 
{ 
    cout << val1 << " " << val2 << endl; 
} 

print(*func(1), *func(2)); 

Este código es muy mala. Se basa en el orden de evaluación de los parámetros de impresión. Imprimirá "1 1" (de derecha a izquierda) o "2 2" (de izquierda a derecha) y . No podemos saber qué. Lo único garantizado por el estándar es que ambas llamadas a func() se completan antes de la llamada a print().

La solución a esto es tener en cuenta que la orden no está especificada, y escribir programas que no dependen del orden de evaluación. Por ejemplo:

int val1 = *func(1); 
int val2 = *func(2); 
print(val1, val2); // Will always print "1 2" on any compiler. 

¿Es necesario que la función de llamada debe ser implementado utilizando únicamente la pila. ¿Qué dice C/C++ estándares sobre esto?

Esto se conoce como "convención de llamadas" y nada que el estándar especifique en absoluto. Cómo se pasan los parámetros (y los valores de retorno) depende completamente de la implementación. Se podrían pasar en los registros de la CPU o en la pila, o de alguna otra manera. La persona que llama podría ser la responsable de presionar/hacer saltar los parámetros en la pila, o la función podría ser responsable.

El orden de evaluación de los parámetros de la función solo está asociado de algún modo con la convención de llamada, ya que la evaluación se produce antes de llamar a la función. Pero, por otro lado, ciertos compiladores pueden optar por poner el parámetro más a la derecha en un registro de CPU y el resto de ellos en la pila, como un ejemplo.

0

Solo para hablar de C idioma, el orden de evaluación dentro de los parámetros de la función depende del compilador. desde El lenguaje de programación C de Brian Kernighan y Dennis Ritchie;

Del mismo modo, el orden en que se evalúan los argumentos de la función no es especificado, por lo que la declaración

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

puede producir resultados diferentes con diferentes compiladores, dependiendo de si n se incrementa antes de poder se llama. La solución , por supuesto, es escribir

++n;

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

Cuestiones relacionadas