Funciones

9. Macros

Directivas del pre procesador 

Las directivas de preprocesador son líneas incluidas en el código de los programas precedidas por un signo de almohadilla (#).  Recordemos que #define, # include lo usan. Estas líneas no son declaraciones de programa, sino directivas para el preprocesador. 

El preprocesador examina el código antes de que comience la compilación real del código ( hace varias pasadas) y resuelve todas estas directivas antes de que cualquier código sea generado por declaraciones regulares.

Estas directivas de preprocesador se extienden solo a través de una única línea de código. 

Tan pronto como se encuentra un carácter de nueva línea, finaliza la directiva del preprocesador para esa línea y continúa con la próxima.

No se espera ningún punto y coma (;) al final de una directiva de preprocesador, por eso #define y #include no llevan ";" al final de las líneas.

La única forma en que una directiva de preprocesador puede extenderse a través de más de una línea es precediendo el carácter de nueva línea al final de la línea con una barra invertida (\).

Veamos un ejemplo de una función macro.



// function macro
#include <iostream>
using namespace std;

#define getmax(a,b) ((a)>(b)?(a):(b))

int main()
{
  int x=5, y;
  y= getmax(x,2);
  cout << y << endl;
  cout << getmax(7,x) << endl;
  return 0;
}
Vemos en este caso que el #define getmax, define una macro usando el operador ternario o condicional.  Una macro puede verse como una función y trabajar de la misma manera, pero las macros NO son usadas en tiempo de ejecución si no durante el preprocesamiento. Esto en algunas oportunidades puede arrojar resultados que no deseamos. Veamos algún ejemplo. 
El siguiente código utiliza la función rand() para generar números aleatorios. Si uso rand()%10 , esto me arroja los restos de números aleratorios divididos por 10, por lo tanto estos serán números: 0,1,2,3,4,5,6,7,8,9  => [0;9)

// function macro
#include <iostream>
//Esta macro regresa 5 o el otro argumento si es mayor a 5.
#define max(a,b) (a<b?b:a)
using namespace std;

//Muestra 20 números entre [5, 10)
int main()
{
  for (int i=0; i<20 ; i++)
  //rand()%10, genera números  [0;9)
  cout << max((rand()%10),5)<< endl;
  return 0;
}

Este código que utiliza una función macro para buscar el máximo valor entre un rango de [5,10)

5 5 5 9 2 5  9 6 6 6 8  5  5 0 3 5 5  5

 pero vemos que pese a que el código compila y corre .. la salida NO está bien, ya que claramente NO deberían aparecer números como el 0,1,2,...

Esto sucede por que el preprocesador REEMPLAZA LA MACRO en CADA línea donde aparece:

max((rand()%10),5)  por --->>>   (rand()%10,5) ? rand()%10

y esto es por que la macro se interpreta de la siguiente manera:

max((rand()%10),5)
{
if (rand()%10)<5)
    return 5
else
    return (rand()%10) 
}

Y aquí claramente podemos ver el error...en el else. Cuando llegue al else.. regresa  rand()%10 que puede ser menor a 5.


// function macro #include <iostream> using namespace std; int max(int,int); int main() { for (int i=0; i<20 ; i++) cout << max((rand()%10),5)<< endl; return 0; } int max(int a,int b) {return ((a)>(b)?(a):(b));}


Esta código si arrojaría los valores esperado.