¿Qué es la evaluación de argumentos?

Herbert Schildt dice:

En algunas situaciones, la función real se debe usar en lugar de la función-como-macro, por ejemplo: donde se debe minimizar el tamaño del código o donde un argumento no se debe evaluar más de una vez.

¿Qué quiere decir con “un argumento no debe ser evaluado más de una vez?”

Tomemos una macro para calcular el máximo de dos valores:

#define MAX(a, b) ((a) < (b) ? (a) : (b)) 

Entonces lo usamos así:

 int x = 5; int y = 10; int max = MAX(x++, y++); 

Entonces la macro se expande a

 int max = ((x++) < (y++) ? (x++) : (y++)); 

Como puede ver, la operación de incremento en x o y sucederá dos veces , no lo que sucedería si tuviera una función donde cada argumento que pase se evalúa solo una vez.


Otro punto importante es el uso de paréntesis en la macro. Tomemos otra macro simple:

 #define MUL(a, b) a * b 

Ahora si invocas la macro como

 int sum = MUL(x + 3, y - 2); 

entonces la expansión se convierte en

 int sum = x + 3 * y - 2; 

Que por precedencia del operador es igual a

 int sum = x + (3 * y) - 2; 

A menudo no es exactamente lo que se esperaba, si se espera (x + 3) * (y - 2) .

Este problema también se "resuelve" mediante el uso de funciones.

A veces los argumentos tienen efectos secundarios .

Por ejemplo, el valor de i++ es i , pero i se incrementa en 1. Como resultado, el valor de i++ siguiente será i + 1 .

En una macro, los argumentos se evalúan cada vez que se solicita, lo que genera valores resultantes; En una función, los argumentos (reales) se evalúan y se copian en argumentos (formales) dentro de la función, descartando los efectos secundarios.

Al implementar una función, no le importan los efectos secundarios. Sin embargo, la promoción y conversión de tipos implícitos pueden ser propensos a errores en su lugar.