2010-05-11 18 views
14

En eclipse, cada vez que creo una nueva clase de C++ o C archivo de cabecera, obtengo el siguiente tipo de estructura. Digo creo encabezado del archivo example.h, me sale esto:Directiva de preprocesador #ifndef para C/C++ código

/*Comments*/ 
#ifndef EXAMPLE_H_ 
#define EXAMPLE_H_ 
/* Place to put all of my definitions etc. */ 
#endif 

Creo ifndef está diciendo que si EXAMPLE_H_ no está definido, lo definen, que puede ser útil dependiendo de la herramienta que se utiliza para compilar y vincula tu proyecto. Sin embargo, tengo dos preguntas:

  1. ¿Es esto bastante común? No lo veo con demasiada frecuencia. Y es una buena idea usar esa rúbrica, o debería ir directamente a definir su código.

  2. ¿Qué es EXAMPLE_H_ exactamente? ¿Por qué no ejemplo.h, o solo ejemplo? ¿Hay algo especial al respecto, o podría ser solo un artefacto de cómo el eclipse prefiere construir proyectos automáticamente?

+0

en cuenta que todo va en entre el ifndef y la endif, en cualquier caso como un programador de aplicaciones es probable que experimenten. Por lo tanto, no es solo que el #define se defina e incluya una sola vez, sino que todo se define y se incluye una sola vez. –

+0

Buen punto, disculpa por no dejar eso más claro, gracias. –

Respuesta

13

Esto es una construcción común. La intención es incluir el contenido del archivo de encabezado en la unidad de traducción solo una vez, incluso si el archivo de encabezado físico se incluye más de una vez. Esto puede suceder, por ejemplo, si incluye el encabezado directamente en su archivo fuente, y también se incluye indirectamente a través de otro encabezado.

Al poner el envoltorio #ifndef alrededor del contenido, el compilador solo analiza el contenido del encabezado una vez y evita los errores de redefinición.

Algunos compiladores permiten que "#pragma una vez" haga lo mismo, pero la construcción #ifndef funciona en todas partes.

+0

Ah, está bien, entonces la declaración #define está ahí para definir algo, podría reemplazar EXAMPLE_H_ por FOO_BAR_ en ambos casos, y aún así funcionaría, es simplemente mejor para usar EXAMPLE_H_, ya que es mucho menos probable que tenga un conflicto de espacio de nombres que si le diera otro nombre, ¿sí? –

+0

Correcto, normalmente las personas usan el nombre del encabezado con caracteres de subrayado para los caracteres que no son válidos en un identificador. Usar un nombre común que podría chocar derrota el propósito :) – user308405

+0

@Leif Andersen: nombres comunes como el ejemplo pueden chocar. Personalmente, prefijo el nombre del archivo con el espacio de nombre completo ya que es menos probable que choque. He visto a otras personas generar GUID completos para evitar la posibilidad de un choque. –

4

Esta es solo una forma común de proteger sus inclusiones, de esta manera evita que el código se incluya dos veces. Y el identificador utilizado podría ser cualquier cosa, es simplemente una convención hacerlo de la manera descrita.

2

Haga siempre esto en la parte superior de un archivo de encabezado. Por lo general se llama guardia de encabezado o protector de inclusión.

Lo que hace es hacerlo de manera que si un archivo de encabezado se incluyera varias veces, solo se incluya una vez. Si no lo hace, terminará con errores sobre cosas que se definen varias veces y cosas por el estilo.

La definición exacta no importa demasiado, aunque normalmente se trata de una variación en el nombre del archivo. Básicamente, está comprobando si la macro dada se ha definido. Si no lo ha hecho, defínalo y continúe incluyendo el archivo. Si tiene, entonces debe haber incluido el archivo previamente, y el resto del archivo se ignora.

2

Esto es un protector de inclusión. Garantiza que un encabezado esté incluido no más de una vez.

Por ejemplo, si tuviera que:

#include "example.h" 
#include "example.h" 

La primera vez que se incluye la cabecera, no se definiría EXAMPLE_H_ y se especificaría el bloque si. EXAMPLE_H_ se define entonces por la directiva #define, y se evalúan los contenidos del encabezado.

La segunda vez que se incluye el encabezado, EXAMPLE_H_ ya está definido, por lo que el bloque if no se vuelve a ingresar.

Esto es esencial para ayudar a garantizar que no infrinja la regla de una definición. Si define una clase en un encabezado que no incluye resguardos e incluye ese encabezado dos veces, obtendrá errores de compilación debido a la violación de la regla de una definición (la clase se definiría dos veces).

Si bien el ejemplo anterior es trivial y puede ver fácilmente que incluye example.h dos veces, los encabezados frecuentes incluyen otros encabezados y no es tan obvio.

+0

¡No, no lo hace! Garantiza que esté incluido NO MÁS DE UNA vez :-) – Vicky

4

¿Es común? Sí - todos Los archivos de encabezado C y C++ deben estructurarse así.EJEMPLO_H es un protector de encabezado, evita que el código en el encabezado se incluya más de una vez en la misma unidad de traducción, lo que daría como resultado múltiples errores de definición. El nombre EXAPMLE_H se elige para que coincida con el nombre del archivo de encabezado que guarda: debe ser único en su proyecto y tal vez también en todo el mundo. Para tratar de asegurar esto, es normal prefijo o sufijo con el nombre del proyecto:

#define MYPROJ_EXAMPLE_H 

por ejemplo, si su proyecto se llama "miproyecto". No se sienta tentado a pensar que el prefijo con guiones bajos lo hará mágicamente único, por cierto, los nombres como _EXAMPLE_H_ y __EXAMPLE_H__ son ilegales, ya que están reservados para la implementación del idioma.

0

Esto se llama "incluir guardia" y es de hecho una expresión común para los archivos de encabezado C/C++. Esto permite que el archivo de encabezado se incluya varias veces sin multiplicar, incluido su contenido.

El nombre EXAMPLE_H_ es una convención arbitraria pero debe obedecer las reglas de denominación para las macros del preprocesador C, que excluye nombres como example.h. Como las macros C están todas definidas en un solo espacio de nombres global, es importante que no tenga diferentes archivos de encabezado que usen el mismo nombre para su protector de inclusión. Por lo tanto, es generalmente una buena idea incluir el nombre de su proyecto o biblioteca en el nombre de la guardia incluir:

#ifndef __MYPROJECT_EXAMPLE_H__ 
... 
+3

Excepto que los nombres que comiencen con un guión bajo seguido de una letra mayúscula u otro guión bajo están reservados para la implementación (es decir, no inicie sus nombres de protector de inclusión con un guión bajo). –

+0

@James y también cualquier identificador que contenga dos guiones bajos en una fila (es decir, no solo al principio). En otras palabras, esta respuesta está llena de violaciones. ;) –

2

consideran este foo.c

archivo: Barra de

#include foo.h 
#include bar.h 

Archivo .h

#include <iostream> 
#include foo.h 

Ahora, cuando compilamos foo.c, tenemos foo.h allí dos veces! Definitivamente no queremos esto, porque todas las funciones arrojarán errores de compilación la segunda vez.

Para evitar esto, colocamos el INCLUDE GUARD en la parte superior. De esta forma, si ya se ha incluido, definimos una variable de preprocesador para indicarnos que no la vuelva a incluir.

Es muy común (a menudo obligatorio), y muy frustrante si alguien no pone uno allí. Usted should puede simplemente esperar que cada archivo .h tenga un protector de encabezado cuando lo incluya. Por supuesto, sabes lo que dicen cuando asumes cosas ("te burla de ti y de mí"), pero eso debería ser algo que esperas ver.

1

U personas significan que tengo que colocar el protector de encabezado para cada archivo de encabezado que quiero inculcar i, e .. tengo los siguientes archivos de encabezado para incluir abc.h y def.h que tengo que colocar guardia de cabecera de la siguiente manera #ifndef abc_h #define abc_h y #ifndef def_h #define def_h

Cuestiones relacionadas