[C con Clase] macros en C/C++

Ferran Ferri ferranferri en gmail.com
Jue Sep 25 17:30:16 CEST 2008


Algo que habria que mencionar es el peligro de las macros. Es mucho mejor
usar funciones inline que las macros. Recuerda que una macro no compruba los
valores de los parametros, cuando la funcion si lo hace.

2008/9/15 Steven Davidson <srd4121 en njit.edu>

> Hola Leonel,
>
> Leonel Florín Selles wrote:
> > hola amigos:
> >
> > bueno les escribo para hacerle una pregunta a la cual le conoscon la
> > respuesta, pero le conosco la respuesta porque, bueno, es decir,
> > tengo duda sobre un tema, el cual me lo explicaron, bueno me dijero,
> > esto es asi y ya, no me explicaron. la cosa es
> >
> > las macros son creadas con la directiva de procesador
> >
> > #define
> >
> > lo que el texto de reemplazo es una operación, la cual puede tener
> > argumentos o no, me sentro en macros con argumentos, entonces, para
> > poder pasarle un argumento a la macro tengo que poner () al final
> > del nombre del identificador de la macro, es decir
> >
> > ejemplo:
> >
> > #define AREA(b) 3.14 * (x) * (x)
> >
>
> Esta macro no está bien definida. Sospecho que quieres que 'b' sea el
> parámetro o argumento que es 'x'. La definición debería ser la siguiente:
>
> #define AREA(b) 3.14 * (b) * (b)
>
> Ahora, cualquier expresión pasada a 'AREA()' como argumento sustituye a
> 'b'.
>
> > y para que funciones
> >
> > area = AREA(2);
> >
> > ahora, lo que no tengo entendido es, cada vez que valla a pasarle
> > argumentos a la macro tengo que utilizar esta forma
> >
> > #define identificador(variable) ..........
> >
>
> En primer lugar, esto es la definición de la macro. En segundo lugar, no
> sugiero pensar que son "variables", sino más bien constantes.
>
> Para usar la macro, debemos escribir el identificador seguido
> inmediatamente por la apertura de paréntesis. Si existe algún carácter
> blanco entre el nombre y el paréntesis, entonces no se considera una
> macro sino posiblemente una función de C/C++. Por ejemplo,
>
> int area = AREA(2);   // usamos la macro AREA()
>
> int area = AREA (3);  // no "llamamos" a una macro
>
> > y porque......
> >
>
> Todo esto se basa en la gramática establecida por el lenguaje de C y C++.
>
> > otra cosa, como sabe #define, que tiene que sustituir a (b) por el
> > valor 2, si #define lo que hace es sustituri a el identificador que
> > es la constante simbolica por el texto de reemplazo que son los
> > simbolos que ponemos despues del identificador en #define.
> >
>
> No veo que el comportamiento de la sustitución que hace el precompilador
> tenga que ver con la sustitución del argumento 'b'. O sea, lo uno no
> quita lo otro.
>
> El precompilador realiza la sustitución cuando se usa la macro. Por
> ejemplo, usando mi definición de 'AREA()', tenemos esto:
>
> area = AREA(2);
>
> El precompilador realiza lo siguiente:
>
> area = 3.14 * (b) * (b);
>
> A su vez, el precompilador sustituye los 'b' por 2. Esto es,
>
> area = 3.14 * (2) * (2);
>
> Podrías pensar que existe dos sustituciones, pero el precompilador
> seguramente hace ambas en un solo paso. El precompilador es muy simple,
> pero no tan "tonto".
>
> > ya probe en el compilador y si no es asi no lo coje, para mi
> > entender, esto se procesa como si fuera una función al pasarle la
> > lista de argumentos que tienen que estar encerrado dentro de
> > parentesis.
> >
>
> No asocies las macros con las funciones de C/C++, porque posiblemente
> empieces a cometer muchos errores. De hecho, la definición de la macro
> que nos diste tiene 2 errores: uno ya te lo corregí. El otro error está
> en que deberías agrupar la definición usando paréntesis. Esto es,
>
> #define AREA(b) (3.14 * (b) * (b))
>
> Si no haces esto, podemos tener problemas que implican comportamientos
> muy raros. Por ejemplo,
>
> res = 5 / AREA(3);
>
> Sin los paréntesis, obtendríamos lo siguiente:
>
> res = 5 / 3.14 * (3) * (3);
>
> El problema es que se hará la división primero y luego las
> multiplicaciones. Sin embargo, esto no es lo que queremos. Con los
> paréntesis, sí conseguimos dividir 5 entre el resultado de 'AREA()'.
> Esto es,
>
> res = 5 / (3.14 * (3) * (3));
>
> Lo mismo sucede con esta condición:
>
> int x;
> ...
> // Si el área es 0
> if( !AREA(x) )  ...
>
> Sin los paréntesis, acabaríamos con lo siguiente:
>
> if( !3.14 * (x) * (x) )  ...
>
> El operador ! tiene mayor precedencia que las multiplicaciones. Esto es
> muy diferente a lo que queremos. Usando paréntesis, logramos nuestro
> objetivo:
>
> if( !(3.14 * (x) * (x)) )  ...
>
> > bueno, yo se que eso es asi por regla, y lo comprendo y lo utilizo,
> > pero alguien tiene una explicación mejor.
> >
>
> No sé que otra explicación quieres que haya. Si preguntas acerca de la
> lógica que sigue el preprocesador para llevar a cabo la sustitución o,
> como se suele decir, la expansión, entonces sinceramente no hay una
> respuesta exacta, ya que un preprocesador puede ser diferente a otro. Lo
> que sí tienen en común es el resultado de las expansiones.
>
> Ten presente que el preprocesador modifica el código fuente;
> básicamente, reprograma tu programa. Como el código fuente no es más que
> un fichero de texto, el preprocesador se basa en manejar caracteres y
> cadenas de caracteres. La definición de la macro es una mera cadena que
> el preprocesador guarda en su programa. Lo normal es que el
> preprocesador tiene una tabla de símbolos y definiciones. Por ejemplo,
>
>  Símbolo |    Definición    | Argumentos
> ---------+------------------+------------
>   AREA   | 3.14 * (b) * (b) |      b
>
>
> Espero que esto te oriente y sea lo que nos has pedido.
>
> Steven
>
>
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20080925/381acd67/attachment.html>


Más información sobre la lista de distribución Cconclase