sábado, 30 de abril de 2011

macros en C


En el tutorial anterior hable sobre las funciones
plantilla
y hacia una comparación con el procesador
de macros de C, ahora voy a mostrar una
reimplementación, utilizando cpp (C Pre Procesor),
el siguiente programa esta escrito en C, no en C++, aunque
se puede compilar con un compilador de C++, la diferencia
es mínima, solo cambian los archivos de cabecera (stdio.h
en vez de iostream) y que se usa printf en vez de cout.

 1 /**********************************************
 2    * Name:     print_size_macro.c
 3    * Created:   18-Abr-2011
 4    * Author:    Gabriel Espinoza
 5      <virtuosonic@users.sourceforge.net>
 6    * License:     MIT
 7    ********************************************/
 8  #include <stdio.h>
 9  
10  #define print_size(x) \
11      printf("  %s  %i bits\n", \
12      #x,sizeof(x)*8)
13  
14  int main()
15  {
16      puts("types size:");
17      print_size(char);
18      print_size(short);
19      print_size(int);
20      print_size(long);
21      print_size(float);
22      print_size(double);
23      print_size(long double);
24  }

Toda la acción sucede entre la linea 10 y 12,
donde se define el macro print_size(), este
macro se expande simplemente a una llamada
a la función printf, lo que importa es como
se pasan los parametros, %s se sustituye
por una cadena de carateres y %i por un
numero entero, # convierte el parametro
del macro en una cadena de caracteres por ejemplo
char se convierte en "char". Tambien
se podria haber colocado el ';' dentro del macro,
pero preferi no hacerlo para ponerlo en cada
llamada al macro para mantener el estilo.

En la función main empezamos con una
llamada a puts que escribe en la salida
estandar, usamos esta función en vez de printf
por que printf es una función muy compleja
y solo deberiamos usarla para cosas complejas, a
continuacion aparecen varias llamadas a print_size y
termina nuestro programa.

Comparativa con plantillas

En este ejemplo especifico podemos ver una ventaja,
en la implementación anterior usabamos
type_id(T).name(), esto tenia la desventaja que
cada compilador produce diferente salida, en esta siempre
sera uniforme, lo que aumenta la portabilidad entre
compiladores. Pero no debemos de ver los macros
como algo inocente, los macros podrian usarse de
maneras que no fueron pensadas, por ejemplo
intenta agregar esto:

 char c[256];
 print_size(c);

Nota: en Visual Studio para que compile
si agregas las dos lineas anteriores debes
declarar char c[256]; antes de la primera
llamada a print_size.

Todavia mas raro prueba esto

 print_size(12468944444444444444);

Luego lo puedes cambiar un poco

 print_size(12468944.444444444444);

Y para perder el sentido por completo:

 print_size(0);
 print_size(0.0);

Pruebenlo, en serio, los macros no son tan buenos.


Bajar el codigo de este programa

No hay comentarios:

Publicar un comentario