Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve...

26
Macros en C MIS. Lizbeth Alejandra Hernández González Programación de Sistemas

Transcript of Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve...

Page 1: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Macros en C

MIS. Lizbeth Alejandra Hernández González

Programación de Sistemas

Page 2: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Macros en C

• Usa un preprocesador de macros

• Remueve todos los comentarios del código

fuente

• Efectúa una serie de sustituciones conceptuales

basadas en el código pasando el resultado al

compilador.

Page 3: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

1. # include <stdio.h>2.3. # define INICIO 0 /* Punto de inicio del bucle */4. # define FINAL 9 /* Fin del bucle */5. # define MAX(A,B) ((A)>(B)?(A):(B)) /* Definición macro de Max */6. # define MIN(A,B) ((A)>(B)?(B):(A)) /* Definición macro de Min */7.8. int main( )9. {10. int indice, mn, mx ;11. int contador = 5 ;12.13. for (indice = INICIO ; indice <= FINAL ; indice++)14. {15. mx = MAX(indice, contador) ;16. mn = MIN(indice, contador) ;17. printf ( "Max es %d y min es %d\n", mx, mn) ;18. }19. return 0 ;20. }

Page 4: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Resultado de la ejecución:

• Max es 5 y min es 0

• Max es 5 y min es 1

• Max es 5 y min es 2

• Max es 5 y min es 3

• Max es 5 y min es 4

• Max es 5 y min es 5

• Max es 6 y min es 5

• Max es 7 y min es 5

• Max es 8 y min es 5

• Max es 9 y min es 5

Page 5: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• #define es la manera para declarar todas las

macros y definiciones.

• el compilador va a la etapa del preprocesador

para resolver todas las definiciones,

• P.e. se buscará cada lugar en el programa

donde se encuentre la palabra INICIO y será

reemplazada con un cero

• El compilador en sí jamás verá la palabra

INICIO.

• Es una práctica común en C utilizar mayúsculas

para constantes simbólicas y minúsculas para

variables.

Page 6: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• cada vez que el preprocesador encuentra la

palabra MAX (termino1, termino2) espera

encontrar dos términos

• el primer término reemplazará cada A en la

segunda parte de la definición, y el segundo

término reemplazará cada B en la segunda

parte de la definición.

• línea 15, indice será sustituída por cada A, y

contador será sustituida por cada B.

Page 7: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• antes de que la línea 15 sea entregada al

compilador, será modificada:

Definición:

# define MAX(A,B) ((A)>(B)?(A):(B))

15 mx = MAX(indice, contador) ;

15 mx = ((index)>(count) ? (index) : (count))

Page 8: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Una macro equivocada

#define EQUIVOCADA(A) A*A*A /* Macro EQUIVOCADA para el cubo */

#define CUBO(A) (A)*(A)*(A) /* Macro correcta para el cubo */

#define CUADRADO(A) (A)*(A) /* Macro correcta para el cuadrado */

#define SUMA_EQUIVOCADA(A) (A)+(A) // Macro equivocada para la suma

#define SUMA_CORRECTA(A) ((A)+(A)) /* Macro correcta para la suma */

#define INICIO 1

#define FINAL 7

Page 9: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

int main( ){

int i, offset ;offset = 5 ;for (i = INICIO ; i <= FINAL ; i++){

printf ("El cuadrado de %3d es %4d, y su cubo es %6d\n",i+offset, CUADRADO(i+offset), CUBO(i+offset)) ;printf ("El cubo equivocado de %3d es %6d\n",i+offset, EQUIVOCADA(i+offset)) ;

}printf ("\nProbamos la macro de suma\n") ;for (i = INICIO ; i <= FINAL ; i++){printf ("La macro de suma EQUIVOCADA = %6d, y la correcta = %6d\n",5*SUMA_EQUIVOCADA(i), 5*SUMA_CORRECTA(i)) ;}return 0 ;

}

Page 10: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales
Page 11: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Necesidad de paréntesis

• Los paréntesis son necesarios para agrupar

adecuadamente las variables.

• Si i es 1 esperamos el cubo de (1+5=6) = 216

• Cuando se usa CUBO(A) (A)*(A)*(A)

▫ (1+5)*(1+5)*(1+5) = 6*6*6 = 216.

• Cuando se usa EQUIVOCADA(A) A*A*A

1+5*1+5*1+5 = 1+5+5+5 = 16

resultado erróneo.

Page 12: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Suma equivocada

▫ #define SUMA_EQUIVOCADA(A) (A)+(A)

▫ #define SUMA_CORRECTA(A) ((A)+(A))

• 5*SUMA_EQUIVOCADA(i) con i=1,

• resultado 5*1+1 5+1= 6,

• el resultado esperado era 5*(1+1) = 5*2 = 10

• usando SUMA_CORRECTA, esto se debe a losparéntesis extra

• NOTA: Agregar paréntesis a cada término y acada expresión (corregir CUBO)

Page 13: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Compilación condicional1. #include <stdio.h>

2. #include <stdlib.h>

3. # define OPCION_1 /* Esto define el control del preprocesador */

4. //# undef OPCION_1

5. # ifdef OPCION_1

6. int contador_1 = 17; /* Esto existe solo si OPCION_1 es definido */

7. # endif

8. int main( )

9. {

10. int indice ;

11. for (indice = 0 ; indice < 6 ; indice++)

12. {

13. printf ("En el bucle, indice = %d", indice) ;

14. # ifdef OPCION_1

15. printf (" contador_1 = %d", contador_1) ; /* puede desplegarse */

16. # endif

17. printf ("\n") ;

18. }

19. system("PAUSE");

20. return 0 ;

21. }

22. # undef OPCION_1

Page 14: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Pruebe el programa

• ¿Cuál es la salida?

• Comente la línea 3

• ¿Cuál es la salida?

• Descomente la línea 3 y descomente la línea 4

• ¿Cuál es la salida?

Page 15: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Ifndef "si no definido".1. #include <stdio.h>

2. #include <stdlib.h>

3. # define OPCION_1 /* Esto define el control al preprocesador */

4. # define MUESTRA_DATO /* Si es definido, se muestra*/

5. # ifndef OPCION_1

6. int contador_1 = 17; /* Esto existe si OPCION_1 no es definido */

7. # endif

8. int main( )

9. {

10. int indice ;

11. # ifndef MUESTRA_DATO

12. printf ("MUESTRA_DATO no está definido en el codigo\n") ;

13. # endif

14. for (indice = 0 ; indice < 6 ; indice++)

15. {

16. # ifdef MUESTRA_DATO

17. printf ("En el bucle, indice = %d", indice) ;

18. # ifndef OPCION_1

19. printf (" contador_1 = %d", contador_1); /* Esto puede mostrarse*/

20. # endif

21. printf ("\n") ;

22. # endif

23. }

24. system("PAUSE");

25. return 0 ;

26. }

Page 16: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Correr el programa

• Verificar la salida original

• Verificar la salida comentando la línea 3

Page 17: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Procesador de macros M4

Page 18: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Procesador de macros M4

• Funciona como el procesador de macros de C.

• Utiliza un lenguaje de macros diferente y de

propósito general; lo cual resulta más potente.

• Ejecutar m4 sin argumentos:

▫ el comando espera texto por la entrada estándar,

▫ tras cada línea introducida, ésta se procesa y se

imprime el resultado por la salida estándar.

• También puede recibir archivos

Page 19: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• La mayor utilidad que se le ha dado a M4 ha

sido en las famosas autotools de GNU

(autoconf, automake, etc.)

• Otro ejemplo es utilizar M4 para escribir

páginas web (creando una abstracción por

encima del HTML).

Page 20: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Utilización de macros

• Llamada a macros:

1. CANTINFLAS

2. Hola señor CANTINFLAS

3. Hola señor CANTINFLAS()puntoycoma.

4. Hola señor CANTINFLAS(punto, y, coma).

5. Hola señor CANTINFLAS(punto y coma).

Page 21: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• La macro que nos permite definir nuevas

macros: define

• admite dos argumentos: el nombre de la nueva

macro y el texto por el que será reemplazada

cada aparición de dicha macro:

▫ define(`CANTINFLAS', 'Bigote')

▫ define(`BOLD', `<b>$1</b>')

Ej. BOLD(hola) será substituido por <b>hola</b>

▫ define(HOLA, Hola mundo cruel)

• $0 que se expande como el nombre de la macro

Page 22: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Otros modificadores

• $* expande todos los argumentos separados por

comas.

• $@ hace lo mismo pero además quotea el

resultado para evitar expansiones del mismo.

• $# se expande como el número de argumentos

pasados a la macro.

Page 23: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Comentarios

• dnl Comentario que no aparecerá en el

resultado.

• # Comentario que sí aparecerá en el resultado

Page 24: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

Cadenas protegidas

• Cuando hablamos de una expansión nos referimos a

dos cosas:

▫ Expandir una macro o

▫ Si se trata de un texto rodeado por ` ' simplemente

se eliminan las comillas.

• el proceso de expansión de una macro es recursivo:

1. Expansión de los argumentos.

2. Se procede a la substitución del texto.

3. Se vuelve a procesar el resultado de esta

expansión.

Page 25: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• Saber proteger el texto quoteándolo.

• Para la inclusión de cadenas literales en

el argumento de una macro basta con

rodearla de comillas dobles, p.e.:

▫ define(`CANTINFLAS', `$1')

▫ Hola señor CANTINFLAS(``Y esto aparece tal

cual, metamos lo que metamos'‘)

Page 26: Macros en C - Universidad Veracruzana · Macros en C •Usa un preprocesador de macros •Remueve todos los comentarios del código fuente •Efectúa una serie de sustituciones conceptuales

• Si necesitamos que una macro se expanda entre

texto que no está separado por espacios

podemos usar la cadena vacía `'. Por ejemplo:

• eseCANTINFLASpoderoso (no válido)

• ese`'CANTINFLAS`'poderoso

• anti`'CANTINFLAS()

• M4 tiene macros para implementar

condicionales, como ifdef e ifelse