stringtranslate.com

incluir guardia

En los lenguajes de programación C y C++ , una protección #include , a veces llamada protección de macro , protección de encabezado o protección de archivo , es una construcción particular utilizada para evitar el problema de la doble inclusión cuando se trata con la directiva include .

El preprocesador de C procesa directivas de la forma #include <file>en un archivo fuente ubicando el asociado fileen el disco y transcluyendo ("incluyendo") su contenido en una copia del archivo fuente conocida como unidad de traducción , reemplazando la directiva include en el proceso. Los archivos incluidos en este sentido son generalmente archivos de encabezado , que normalmente contienen declaraciones de funciones y clases o estructuras .

Si una directiva #include para un archivo determinado aparece varias veces durante la compilación (es decir, porque apareció en varios otros encabezados), el archivo se procesa nuevamente cada vez. Sin embargo, si ciertas construcciones del lenguaje C o C++ se definen dos veces , la unidad de traducción resultante no es válida . Las protecciones #include evitan que surja esta construcción errónea al definir una macro de preprocesador cuando se incluye un encabezado por primera vez y detectar su presencia para omitir el contenido del archivo en inclusiones posteriores.

La adición de protecciones #include a un archivo de encabezado es una forma de hacer que ese archivo sea idempotente . Otra construcción para combatir la doble inclusión es #pragma once , que no es estándar pero es compatible casi universalmente entre los compiladores de C y C++ .

Doble inclusión

Ejemplo

El siguiente código C demuestra un problema real que puede surgir si faltan las protecciones #include:

Archivo "abuelo.h"

struct foo { int miembro ; };    

Archivo "parent.h"

#include "abuelo.h" 

Archivo "child.c"

#include "abuelo.h" #include "padre.h"  

Resultado

struct foo { int miembro ; }; struct foo { int miembro ; };        

En este caso, el archivo "child.c" ha incluido indirectamente dos copias del texto del archivo de encabezado "grandparent.h". Esto provoca un error de compilación , ya que el tipo de estructura foose definirá dos veces. En C++, esto se denominaría una violación de la regla de una sola definición .

Uso de protectores #include

Ejemplo

En esta sección, se utiliza el mismo código con la adición de protecciones #include. El preprocesador de C preprocesa los archivos de encabezado, incluyéndolos y preprocesándolos nuevamente de manera recursiva . Esto dará como resultado un archivo fuente correcto, como veremos.

Archivo "abuelo.h"

#ifndef ABUELO_H #define ABUELO_Hstruct foo { int miembro ; };    #endif /* ABUELO_H */

Archivo "parent.h"

#include "abuelo.h" 

Archivo "child.c"

#include "abuelo.h" #include "padre.h"  

Resultado

struct foo { int miembro ; };    

Aquí, la primera inclusión de "grandparent.h" tiene la macro GRANDPARENT_Hdefinida. Cuando "child.c" incluye "grandparent.h" la segunda vez (mientras incluye "parent.h"), como la #ifndefprueba devuelve falso, el preprocesador salta a #endif, evitando así la segunda definición de struct foo. El programa se compila correctamente.

Discusión

Diferentes programadores pueden utilizar diferentes convenciones de nombres para la macro de protección . Otras formas comunes del ejemplo anterior incluyen , (con la información de tiempo apropiada sustituida) y nombres generados a partir de un UUID . (Sin embargo, los nombres que comienzan con un guión bajo y una letra mayúscula (C y C++) o cualquier nombre que contenga un guión bajo doble (solo C++), como y , están reservados para la implementación del lenguaje y no deben ser utilizados por el usuario. [1] [2] )GRANDPARENT_INCLUDEDCREATORSNAME_YYYYMMDD_HHMMSS_GRANDPARENT_HGRANDPARENT__H

Por supuesto, es importante evitar duplicar el mismo nombre de macro include-guard en diferentes archivos de encabezado, ya que incluir el primero evitará que se incluya el segundo, lo que provocará la pérdida de declaraciones, definiciones en línea u otros #includes en el segundo encabezado.

Dificultades

Para que las protecciones #include funcionen correctamente, cada protección debe probar y configurar condicionalmente una macro de preprocesador diferente. Por lo tanto, un proyecto que utilice protecciones #include debe desarrollar un esquema de nombres coherente para sus protecciones de inclusión y asegurarse de que su esquema no entre en conflicto con el de los encabezados de terceros que utilice o con los nombres de las macros visibles globalmente.

#pragma oncePor esta razón, la mayoría de las implementaciones de C y C++ proporcionan una directiva no estándar . Esta directiva, insertada en la parte superior de un archivo de encabezado, garantizará que el archivo se incluya solo una vez. El lenguaje Objective-C (que es un superconjunto de C) introdujo una #importdirectiva que funciona exactamente como #include, excepto que incluye cada archivo solo una vez, lo que evita la necesidad de protecciones #include. [3]

Otros idiomas

Algunos lenguajes admiten la especificación de que el código debe incluirse solo una vez, en el archivo incluido, en lugar de en el incluido (como con los protectores de inclusión de C/C++ y #pragma once):

Véase también

Referencias

  1. ^ Sección 17.4.3.1.2/1 del estándar C++ (ISO/IEC 14882)
  2. ^ Norma C (ISO/IEC 9899) sección 7.1.3/1.
  3. ^ "Objective C: Definición de clases". developer.apple.com . 2014-09-17 . Consultado el 2018-10-03 .
  4. ^ IBM Corporation (agosto de 2017). Enterprise PL/I for z/OS PL/I for AIX Enterprise PL/I for z/OS Language Reference Version 5 Release 1 (PDF) . p. 257 . Consultado el 7 de abril de 2022 .
  5. ^ "include_once (Referencia del lenguaje PHP)".

Enlaces externos