En el lenguaje C, el orden de cálculo de los argumentos de la función no está definido por el estándar (hasta C99 incluido). Los argumentos pueden calcularse de izquierda a derecha, de derecha a izquierda o en cualquier otro orden (a discreción del compilador o de la arquitectura).
void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // ¡el orden de cálculo de x++ y x++ no está definido!
"¿En qué orden se calculan los argumentos de la función en C y se puede confiar en esto al escribir código?"
Un error común es suponer que los argumentos se calculan de izquierda a derecha (por analogía con las expresiones). En la práctica, cada llamada a la función se compila a discreción del compilador (y de la plataforma).
void foo(int a, int b, int c); int x = 1; foo(x++, x++, x++); // el resultado depende del orden de cálculo de los argumentos
La verdadera respuesta: no se puede confiar — ¡el comportamiento no está definido!
Historia
En un producto multiplataforma, un programador escribió
push(stack, stack->size++, data);. En la mayoría de las plataformas funcionó, pero en una, el tamaño de la pila aumentaba antes de pasar los datos, y en otra — después. Los datos se "perdían" o se direccionaban incorrectamente, el error era raro y difícil de depurar.
Historia
En la biblioteca del protocolo de red, la función de registro se llamaba con expresiones-argumentos que incrementaban contadores estadísticos. Los informes de estadísticas se generaban incorrectamente: los índices de los contadores diferían entre clientes, porque se ejecutaban en un orden diferente al esperado.
Historia
En la interfaz de control de hardware, la función de inicialización pasaba punteros y desplazamientos con incrementos dentro de los argumentos (tipo
init(ptr++, cnt++);). En algunos procesadores, el hardware se inicializaba correctamente, mientras que en otros fallaba, y la causa se buscaba durante mucho tiempo en el hardware, aunque el problema estaba en el código C incorrecto.