¿Por qué se usan #ifndef y #define en los archivos de encabezado de C ++?

496

He estado viendo un código como este generalmente al comienzo de los archivos de encabezado:

#ifndef HEADERFILE_H
#define HEADERFILE_H

Y al final del archivo es

#endif

¿Cuál es el propósito de esto?

Asad Khan
fuente
36
+1 - Yo también tuve la misma duda, y obtuve una respuesta mucho más buena aquí, puede ser útil para futuros visitantes: stackoverflow.com/q/3246803/1134940
Abid Rahman K
66
Quiero agregar a esto que también puedes usar #pragma una vez , eso es todo lo que tienes que hacer y sirve para el mismo propósito que ifndef. Para comparar los dos, consulte: stackoverflow.com/questions/1143936/…
Dimensión del
3
Es mejor mencionar qué #pragmaes: activa una función específica del compilador. Aunque #pragma oncees muy ampliamente compatible, no es estándar.
Potatoswatter 01 de
3
@Dimension: la propia documentación de GNU ( info cppo consulte aquí ) dice "no todos los preprocesadores la reconocen, por lo que no puede confiar en ella en un programa portátil". Y GNU cpp optimiza el idioma común y portátil #ifndefpara que sea tan eficiente como #pragma once.
Keith Thompson el
3
Algunas cosas a tener en cuenta: no utilice un nombre de macro que comience con un guión bajo; dichos identificadores están reservados para la implementación. Más sutilmente, #ifndef HEADERFILE_Hpuede violar el espacio de nombres de la implementación del nombre del encabezado para empezar E; los identificadores que comienzan con Ey un dígito o letra mayúscula están reservados para <errno.h>. Sugiero #ifndef H_HEADERFILE.
Keith Thompson el

Respuestas:

527

Esos se llaman #include guardias .

Una vez que se incluye el encabezado, comprueba si HEADERFILE_Hse define un valor único (en este caso ). Luego, si no está definido, lo define y continúa al resto de la página.

Cuando se vuelve a incluir el código, el primero ifndeffalla y se genera un archivo en blanco.

Eso evita la doble declaración de cualquier identificador como tipos, enumeraciones y variables estáticas.

LiraNuna
fuente
1
Koning Baard XIV: VC incluso tiene uno #pragma onceque hace lo mismo :-)
Joey
95
También evita las inclusiones recursivas ... Imagina que "alice.h" incluye "bob.h" y "bob.h" incluye "alice.h" y no tienen guardias incluidos ...
Kevin Dungs
@ Kevin: a eso me refiero. Quería manipular un formulario que fue abierto por el formulario para manipular. Me dio muchos errores y no sabía qué hacer. Me di por vencido =)
66
@ Јοеу: #pragma onceno es portátil; #ifndefSe recomienda el idioma común .
Keith Thompson el
2
@CIsForCookies Ponga "una regla de definición" en su motor de búsqueda favorito.
David Schwartz
33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndefcomprueba si el token dado ha estado #definedantes en el archivo o en un archivo incluido; si no, incluye el código entre este y el cierre #elseo, si no #elseestá presente, la #endifdeclaración. #ifndefa menudo se usa para hacer que los archivos de encabezado sean idempotentes definiendo un token una vez que el archivo se ha incluido y verificando que el token no se haya establecido en la parte superior de ese archivo.

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif
Roy
fuente
44
Los identificadores que comienzan con un guión bajo están reservados; No deberías definirlos tú mismo. Usa algo como #ifndef H_HEADER_NAME.
Keith Thompson el
55
Sé que este es un comentario antiguo, pero en realidad la restricción de subrayado solo se aplica a "identificadores externos", identificadores que podrían terminar en la tabla de símbolos del objeto compilado, es decir, variables globales y nombres de funciones. No se aplica a los nombres de macro.
Stu
1
¿Es cierto el comentario de Stu? Acabo de leer stackoverflow.com/questions/228783/… y ahora no estoy tan seguro.
Será
10

Esto evita la inclusión múltiple del mismo archivo de encabezado varias veces.

#ifndef __COMMON_H__
#define __COMMON_H__
//header file content
#endif

Suponga que ha incluido este archivo de encabezado en varios archivos. Entonces, la primera vez que __COMMON_H__ no está definida, se definirá y se incluirá el archivo de encabezado.

La próxima vez que se defina __COMMON_H__, no se volverá a incluir.

Sandeep_black
fuente
1

Se llaman ifdef o incluyen guardias.

Si escribe un programa pequeño, puede parecer que no es necesario, pero a medida que el proyecto crece, puede incluir intencionalmente o no un archivo muchas veces, lo que puede generar una advertencia de compilación como la variable ya declarada.

#ifndef checks whether HEADERFILE_H is not declared.
#define will declare HEADERFILE_H once #ifndef generates true.
#endif is to know the scope of #ifndef i.e end of #ifndef

Si no se declara, lo que significa que #ifndef genera verdadero, solo la parte entre #ifndef y #endif ejecutada de lo contrario no. Esto evitará volver a declarar los identificadores, enumeraciones, estructura, etc.

Mohit Jain
fuente