Warum werden #ifndef und #define in C ++ - Headerdateien verwendet?

496

Ich habe Code wie diesen normalerweise am Anfang von Header-Dateien gesehen:

#ifndef HEADERFILE_H
#define HEADERFILE_H

Und am Ende der Datei steht

#endif

Was ist der Zweck davon?

Asad Khan
quelle
36
+1 - Ich hatte auch den gleichen Zweifel und bekam hier viel mehr gute Antworten, kann für zukünftige Besucher nützlich sein: stackoverflow.com/q/3246803/1134940
Abid Rahman K
6
Ich möchte hinzufügen, dass Sie #pragma auch einmal verwenden können , das ist alles, was Sie tun müssen, und es dient dem gleichen Zweck wie ifndef. Zum Vergleich der beiden siehe: stackoverflow.com/questions/1143936/…
Dimension
3
Am besten erwähnen, was a #pragmaist: Es aktiviert eine compilerspezifische Funktion. Obwohl #pragma oncees sehr weit verbreitet ist, ist es nicht Standard.
Potatoswatter
3
@Dimension: In der GNU-eigenen Dokumentation ( info cppoder hier ) heißt es: "Sie wird nicht von allen Präprozessoren erkannt, sodass Sie sich in einem tragbaren Programm nicht darauf verlassen können." Und GNU cpp optimiert die gängige und tragbare Sprache #ifndefso effizient wie möglich #pragma once.
Keith Thompson
3
Einige Dinge zu beachten: Verwenden Sie keinen Makronamen, der mit einem Unterstrich beginnt. Solche Kennungen sind der Implementierung vorbehalten. #ifndef HEADERFILE_HKann subtiler den Namespace der Implementierung verletzen, mit dem der Headername anfängt E; Bezeichner, die mit Eund eine Ziffer oder ein Großbuchstabe beginnen, sind vorbehalten <errno.h>. Ich schlage vor #ifndef H_HEADERFILE.
Keith Thompson

Antworten:

526

Diese werden #include Wachen genannt .

Sobald der Header enthalten ist, wird geprüft, ob (in diesem Fall HEADERFILE_H) ein eindeutiger Wert definiert ist. Wenn es dann nicht definiert ist, definiert es es und fährt mit dem Rest der Seite fort.

Wenn der Code erneut ifndefeingefügt wird, schlägt der erste fehl, was zu einer leeren Datei führt.

Dies verhindert die doppelte Deklaration von Bezeichnern wie Typen, Aufzählungen und statischen Variablen.

LiraNuna
quelle
1
Koning Baard XIV: VC hat sogar eine, #pragma oncedie das gleiche tut :-)
Joey
95
Außerdem werden rekursive Einschlüsse verhindert ... Stellen Sie sich vor, "alice.h" enthält "bob.h" und "bob.h" enthält "alice.h" und sie haben keine Include-Wachen ...
Kevin Dungs
@ Kevin: das meine ich. Ich wollte ein Formular manipulieren, das von dem zu manipulierenden Formular geöffnet wurde. Es gab viele Fehler und ich wusste nicht, was ich tun sollte. Ich gab auf =)
6
@ :Οеу: #pragma onceist nicht tragbar; Die gebräuchliche #ifndefRedewendung wird empfohlen.
Keith Thompson
2
@CIsForCookies Geben Sie "one definition rule" in Ihre bevorzugte Suchmaschine ein.
David Schwartz
33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndefprüft, ob das angegebene Token #definedfrüher in der Datei oder in einer enthaltenen Datei war; Wenn nicht, enthält es den Code zwischen ihm und der abschließenden #elseoder, falls keine #elsevorhanden ist, #endifAnweisung. #ifndefwird häufig verwendet, um Header-Dateien idempotent zu machen, indem ein Token definiert wird, sobald die Datei aufgenommen wurde, und überprüft wird, ob das Token nicht oben in dieser Datei festgelegt wurde.

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif
Roy
quelle
4
Bezeichner, die mit einem Unterstrich beginnen, sind reserviert. Sie sollten sie nicht selbst definieren. Verwenden Sie so etwas wie #ifndef H_HEADER_NAME.
Keith Thompson
5
Ich weiß, dass dies ein alter Kommentar ist, aber tatsächlich gilt die Unterstrichbeschränkung nur für "externe Bezeichner" - Bezeichner, die in der Symboltabelle des kompilierten Objekts landen könnten, dh globale Variablen und Funktionsnamen. Dies gilt nicht für Makronamen.
Stu
1
Ist Stu's Kommentar wahr? Ich habe gerade stackoverflow.com/questions/228783/… gelesen und bin mir jetzt nicht so sicher.
Will
9

Dies verhindert, dass dieselbe Header-Datei mehrfach mehrfach aufgenommen wird.

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

Angenommen, Sie haben diese Header-Datei in mehrere Dateien aufgenommen. Wenn __COMMON_H__ zum ersten Mal nicht definiert wird, wird es definiert und die Header-Datei eingeschlossen.

Das nächste Mal wird __COMMON_H__ definiert, sodass es nicht wieder aufgenommen wird.

Sandeep_black
quelle
1

Sie heißen ifdef oder beinhalten Wachen.

Wenn Sie ein kleines Programm schreiben, scheint es, dass es nicht benötigt wird, aber wenn das Projekt wächst, können Sie absichtlich oder unbeabsichtigt eine Datei mehrmals einfügen, was zu einer Kompilierungswarnung wie einer bereits deklarierten Variablen führen kann.

#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

Wenn es nicht deklariert ist, was bedeutet, dass #ifndef true generiert, wird nur der Teil zwischen #ifndef und #endif ausgeführt, andernfalls nicht. Dies verhindert, dass die Bezeichner, Aufzählungen, Strukturen usw. erneut deklariert werden.

Mohit Jain
quelle