Guardias de inclusión #ifndef en C

Jinku Hu 12 octubre 2023
  1. Usar la guardia de inclusión ifndef para proteger contra la inclusión múltiple de archivos de cabecera en C
  2. Utilizar la directiva ifndef para asegurar que las macros no se definen varias veces en C
Guardias de inclusión #ifndef en C

Este artículo demostrará múltiples métodos de cómo usar #ifndef include guards en C.

Usar la guardia de inclusión ifndef para proteger contra la inclusión múltiple de archivos de cabecera en C

Los archivos de cabecera en C se utilizan para definir la interfaz para las funciones implementadas en el archivo fuente con el mismo nombre. La interfaz suele incluir prototipos de funciones, definiciones de estructuras de datos de acceso público y otras cosas diversas.

Tenga en cuenta que los archivos de cabecera pueden incluirse en el archivo fuente varias veces, lo que provoca errores de compilación. Normalmente, esto se evita con la directiva del preprocesador #ifndef, que se llama wrapper #ifndef. Cuando el contenido del fichero de cabecera está encerrado en la estructura mostrada en el siguiente ejemplo, donde la directiva #ifndef MY_GUARD es el punto de partida y #endif el final. La directiva #ifndef comprueba si la macro MY_GUARD está definida, si no lo está continúa y la define con la siguiente directiva. En caso de que el usuario incluya la misma cabecera por segunda vez, la directiva ifndef evaluará false e ignorará el código anterior a la directiva #endif. Como resultado, el compilador obtendrá sólo una copia del código de este fichero de cabecera y lo traducirá con éxito.

#include <stdio.h>

#ifndef MY_GUARD
#define MY_GUARD 1

#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)

int power(int base, int n) {
  int p = base;
  for (size_t i = 0; i < n; i++) {
    p *= base;
  }
  return p;
}
#endif

Otro método para conseguir los mismos resultados es incluir la directiva #pragma once en el fichero de cabecera. El preprocesador escanea esos ficheros de cabecera sólo una vez y garantiza que no se vuelvan a leer. Una desventaja del siguiente método es que tiene poca portabilidad a través de los diferentes preprocesadores, por lo que uno podría querer seguir con el método envolvente #ifndef para asegurar una mejor flexibilidad del código base.

#include <stdio.h>

#pragma once

#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)

int power(int base, int n) {
  int p = base;
  for (size_t i = 0; i < n; i++) {
    p *= base;
  }
  return p;
}

Utilizar la directiva ifndef para asegurar que las macros no se definen varias veces en C

Alternativamente, podemos utilizar la directiva ifndef para comprobar si la expresión de macro dada ya ha sido definida. La lógica funciona exactamente como en el ejemplo anterior; si la expresión no está definida, la siguiente directiva #define se procesa en consecuencia. La única línea entre el #ifndef y el #endif es una definición de macro, lo que significa que en caso de que la condición sea falsa, sólo se salta la definición de la macro dada.

#include <stdio.h>
#include <stdlib.h>

#define PER(D) #D

#ifndef DLEVEL
#define DLEVEL 6
#endif

int main() {
  for (int j = 0; j < DLEVEL; ++j) {
    printf("%s\n", PER(stringify this));
  }

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook