Google
 

lunes, septiembre 11, 2006

¿Porqué las macros de C apestan?

Imaginad que queremos hacer una macro que nos devuelva el cuadrado de un número. En un primer intento escribiremos:
#define cuadrado(x) x*x
Pero sin darnos cuenta hemos caído en una trampa terrible. En un primer intento nos damos cuenta que 2/cuadrado(10) no funciona porque se expande a 2/10*10. Para intentar solucionarlo cambiamos la macro a:
#define cuadrado(x) (x*x)
Acto seguido vemos como no funciona al intentar hacer cuadrado(1+1) porque se expande a (1+1*1+1). Así que intentamos volver a arreglar la macro:
#define cuadrado(x) ((x)*(x))
Pero así y todo nos sigue sin funcionar de forma correcta al hacer:
int x = 2;
cuadrado(x++)
Porque se expande a ((x++)*(x++)). Finalmente intentamos usar otra solución:
int temp_var;
#define cuadrado(x) (temp_var=(x); temp_var*temp_var)
Pero sólo nos funciona con números enteros así que nunca más podrás hacer cuadrado(3.5). Para conseguir una versión de la macro que nos funcione de forma correcta deberemos tirar de extensiones del lenguaje no estándar:
#define cuadrado(x) ({typedef xtype = x; xtype xval = x; xval * xval; })
Una simple macro que en un principio parecía que no sería gran cosa nos ha obligado a usar extensiones del lenguaje que no nos ofrecen ninguna garantía de continuidad ya que no son parte del estándar. Pero es que el sistema de macros de C no acaba aquí, programar una macro que haga algo tan simple como:
strswitch(exp) {
case “hola”: llamar_hola(); break;
case “adios”; llamar_adios(); break;
default: llamar_pordefecto(); break;
}
Es literalmente imposible de llevar a cabo en C.

[Basado en http://lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html]

2 comentarios:

yengamatic dijo...

Las macros de C/C++ tiene utilidades especificas.
Para los ejemplos que has puesto (el tipico de pasar x++ a una macro) se solucionan rapidamente con funciones inline.

samsaga2 dijo...

Es que mientras C/C++ ha ido evolucionando su sistema de macros ha estado totalmente estancando.

Ya se que las comparaciones son odiosas pero despues de usar las macros de lenguajes como Lisp o Ocaml si tengo que programar despues una en C/C++ pienso kkdlvak (= kaka de la vaka).