Zum Inhalt springen

Include-Guard

aus Wikipedia, der freien Enzyklopädie
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 24. April 2012 um 19:32 Uhr durch Plankton314 (Diskussion | Beiträge) (WP:REV Das ist wohl keine Verbesserung). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Der Include Guard (dt: Include Wächter) ist eine Programmiertechnik, um in C oder C++ das Problem der doppelten Einbindung (engl.: double inclusion) zu umgehen.

Dieses Problem tritt auf, wenn innerhalb eines Moduls mehrfach die gleiche Header-Datei eingebunden wird. Das geschieht in der Regel unbeabsichtigt, zum Beispiel wenn mehrere Header-Dateien die gleiche Bibliothek benutzen.

Beispiel

// A.h
const int M = 123;

class A
{ /* ... */ };


// B.h
#include "A.h"

class B : public A
{ /* ... */ };


Im Hauptprogramm möchte man nun sowohl die Klasse A als auch B nutzen:

// program.c
#include "A.h"
#include "B.h"

int main() { /* ... */ }

Der Compiler liefert einen Fehler, weil eine Klasse oder Variable nochmals definiert wird (engl.: redefinition).

#ifndef Wrapper (oder Makro-Guard)

Der #ifndef-Wrapper ist der traditionelle und C-konforme Ansatz. Er versucht das Problem zu lösen, indem er ein eindeutiges Makro beim ersten Einbinden der Header-Datei definiert. Ist dieses Makro bereits definiert, werden die Definitionen des Headers übersprungen:

// A.h
#ifndef _A_H_
#define _A_H_

class A
{ /* ... */ };

#endif /* _A_H_ */

Im obigen Beispiel bewirkt das, dass beim erstmaligen Einbinden von A.h (aus program.cpp) das Makro _A_H_ noch nicht definiert ist und der Präprozessor die Definitionen durchläuft. Beim zweiten Einbinden (aus B.h) ist das Makro bereits definiert und der Präprozessor überspringt den #ifndef .. #endif-Block.

Das eigentliche Problem mit dieser Technik ist die sog. namespace pollution: die definierten Makros liegen im globalen Namensraum und „verschmutzen“ diesen mit steigender Anzahl zusehends. Dem kann durch die Festlegung von Namenskonventionen zwar vorgebeugt werden, dies löst das Problem jedoch nicht[1].

Der CPP, der Präprozessor des GCC, erkennt solche Konstrukte automatisch, merkt sich die entsprechenden Dateien und überspringt diese bei nochmaligem Einbinden[2].

#pragma Guard

Sowohl der Microsoft C/C++ Compiler[3] als auch der GCC[4] unterstützen heute die Präprozessor-Direktive #pragma once. Diese sorgt ebenfalls dafür, dass eine (Header-)Datei nur einmalig eingebunden wird, setzt jedoch auf höherer Ebene an (direkt am Präprozessor) und führt auch keine Makros in den globalen Namensraum ein.

Zur Verwendung genügt es innerhalb der Header-Datei die Anweisung #pragma once einzufügen:

// A.h
#pragma once

class A
{ /* ... */ };

Gerade bei portablem Code muss jedoch beachtet werden, dass dies eine Compiler-spezifische Erweiterung ist und nicht zwingend von jedem C/C++-Compiler unterstützt wird[4].

Siehe auch

Einzelnachweise

  1. Eric Fleegal's WebLog on MSDN Blogs. Abgerufen am 19. August 2011.
  2. Once-Only Headers im GNU CPP Online Manual. Abgerufen am 19. August 2011.
  3. MSDN Visual Studio 2010 - once
  4. a b Alternatives to Wrapper #ifndef im GNU CPP Online Manual. Abgerufen am 19. August 2011.