Datos interesantes sobre macros y preprocesadores en C

En un programa C, todas las líneas que comienzan con # son procesadas por un preprocesador, que es un programa especial invocado por el compilador. con esto queremos decir que el símbolo ‘#’ se usa para procesar la funcionalidad antes que otras declaraciones en el programa, es decir, lo que significa que procesa algún código antes del tiempo de ejecución o durante el tiempo de compilación. En un término muy básico, el preprocesador toma un programa C y produce otro programa C sin ningún # .

Los siguientes son algunos datos interesantes sobre los preprocesadores en C. 

1) Cuando usamos la directiva include , el contenido del archivo de encabezado incluido (después del preprocesamiento) se copia en el archivo actual. 
Los corchetes angulares < y > indican al preprocesador que busque en la carpeta estándar donde se encuentran todos los archivos de encabezado. Las comillas dobles « y « indican al preprocesador que busque en la carpeta actual (directorio actual). 

2) Cuando usamos define para una constante, el preprocesador produce un programa C donde se busca la constante definida y los tokens coincidentes se reemplazan con la expresión dada. Por ejemplo, en el siguiente programa max se define como 100.

C

#include <stdio.h>
#define max 100
int main()
{
    printf("max is %d", max);
    return 0;
}
Producción: 

max is 100

 

 

3) Las macros pueden funcionar como argumentos, los argumentos no se verifican para el tipo de datos. Por ejemplo, la siguiente macro INCREMENT(x) se puede usar para x de cualquier tipo de datos.

C

#include <stdio.h>
#define INCREMENT(x) ++x
int main()
{
    char* ptr = "GeeksQuiz";
    int x = 10;
    printf("%s  ", INCREMENT(ptr));
    printf("%d", INCREMENT(x));
    return 0;
}
Producción: 

eeksQuiz  11

 

4) Los argumentos de macro no se evalúan antes de la expansión de macro. Por ejemplo, considere el siguiente programa

C

#include <stdio.h>
#define MULTIPLY(a, b) a* b
int main()
{
    // The macro is expanded as 2 + 3 * 3 + 5, not as 5*8
    printf("%d", MULTIPLY(2 + 3, 3 + 5));
    return 0;
}
// Output: 16
Producción: 

16

 

El problema anterior se puede resolver usando el siguiente programa 

C

#include <stdio.h>
// here, instead of writing a*a we write (a)*(b)
#define MULTIPLY(a, b) (a) * (b)
int main()
{
    // The macro is expanded as (2 + 3) * (3 + 5), as 5*8
    printf("%d", MULTIPLY(2 + 3, 3 + 5));
    return 0;
}
// This code is contributed by Santanu
Producción: 

40

 

5) Los tokens pasados ​​a las macros se pueden concatenar usando el operador ## llamado operador de pegado de tokens.

C

#include <stdio.h>
#define merge(a, b) a##b
int main() { printf("%d ", merge(12, 34)); }
Producción: 

1234

 

6) Un token pasado a macro se puede convertir en un literal de string usando # antes.

C

#include <stdio.h>
#define get(a) #a
int main()
{
    // GeeksQuiz is changed to "GeeksQuiz"
    printf("%s", get(GeeksQuiz));
}
Producción: 

GeeksQuiz

 

7) Las macros se pueden escribir en varias líneas usando ‘\’. La última línea no necesita tener ‘\’.

C

#include <stdio.h>
#define PRINT(i, limit)                                    \
    while (i < limit) {                                    \
        printf("GeeksQuiz ");                              \
        i++;                                               \
    }
int main()
{
    int i = 0;
    PRINT(i, 3);
    return 0;
}
Producción: 

GeeksQuiz GeeksQuiz GeeksQuiz

 

8) Deben evitarse las macros con argumentos, ya que a veces causan problemas. Y se deben preferir las funciones en línea, ya que hay una evaluación de parámetros de verificación de tipo en las funciones en línea. Desde C99 en adelante, las funciones en línea también son compatibles con el lenguaje C. 

Por ejemplo, considere el siguiente programa. A primera vista, la salida parece ser 1, pero produce 36 como salida.

C

#include <stdio.h>
 
#define square(x) x* x
int main()
{
    // Expanded as 36/6*6
    int x = 36 / square(6);
    printf("%d", x);
    return 0;
}
Producción

36

Pero podemos escribir este código de la siguiente manera para obtener el resultado esperado, es decir, 1:

C

#include <stdio.h>
 
#define square(x) (x * x)
int main()
{
    // Expanded as 36/(6*6)
    int x = 36 / square(6);
    printf("%d", x);
    return 0;
}

Producción

1

Si usamos funciones en línea, obtenemos el resultado esperado. Además, el programa dado en el punto 4 anterior se puede corregir usando funciones en línea.

C

#include <stdio.h>
 
static inline int square(int x) { return x * x; }
int main()
{
    int x = 36 / square(6);
    printf("%d", x);
    return 0;
}
Producción: 

1

 

9) Los preprocesadores también son compatibles con las directivas if-else que normalmente se utilizan para la compilación condicional. 

C

int main()
{
#if VERBOSE >= 2
    printf("Trace Message");
#endif
}
Producción: 

No Output

 

10) Un archivo de encabezado puede incluirse más de una vez directa o indirectamente, lo que genera problemas de redeclaración de las mismas variables/funciones. Para evitar este problema, se utilizan  directivas comodefined , ifdef e ifndef .

11) Hay algunas macros estándar que se pueden usar para imprimir el archivo de programa (__FILE__), la fecha de compilación (__DATE__), la hora de compilación (__TIME__) y el número de línea en código C (__LINE__)

C

#include <stdio.h>
 
int main()
{
    printf("Current File :%s\n", __FILE__);
    printf("Current Date :%s\n", __DATE__);
    printf("Current Time :%s\n", __TIME__);
    printf("Line Number :%d\n", __LINE__);
    return 0;
}
Producción: 

Current File :/usr/share/IDE_PROGRAMS/C/other/081c548d50135ed88cfa0296159b05ca/081c548d50135ed88cfa0296159b05ca.c
Current Date :Sep  4 2019
Current Time :10:17:43
Line Number :8

 

12) Podemos eliminar macros ya definidas usando: 
#undef MACRO_NAME 

C

#include <stdio.h>
#define LIMIT 100
int main()
{
    printf("%d", LIMIT);
// removing defined macro LIMIT
#undef LIMIT
    // Next line causes error as LIMIT is not defined
    printf("%d", LIMIT);
    return 0;
}
// This code is contributed by Santanu

El siguiente programa se ejecuta correctamente ya que hemos declarado LIMIT como una variable entera después de eliminar la macro LIMIT previamente definida 

C

#include <stdio.h>
#define LIMIT 1000
int main()
{
    printf("%d", LIMIT);
// removing defined macro LIMIT
#undef LIMIT
    // Declare LIMIT as integer again
    int LIMIT = 1001;
    printf("\n%d", LIMIT);
    return 0;
}
Producción: 

1000
1001

 

Otro hecho interesante sobre el uso de macros ( #undef )  

C

#include <stdio.h>
// div function prototype
float div(float, float);
#define div(x, y) x / y
 
int main()
{
    // use of macro div
    // Note: %0.2f for taking two decimal value after point
    printf("%0.2f", div(10.0, 5.0));
// removing defined macro div
#undef div
    // function div is called as macro definition is removed
    printf("\n%0.2f", div(10.0, 5.0));
    return 0;
}
 
// div function definition
float div(float x, float y) { return y / x; }
// This code is contributed by Santanu
Producción: 

2.00
0.50

 

Es posible que desee realizar una prueba sobre macros y preprocesadores en C.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *