Headerdateien

Besteht ein Programm aus mehreren Teilen (Modulen), ist es vorteilhaft, Headerdateien zu benutzen. Außerdem kommt es vor, dass Programmierer nach einer gewissen Zeit eigene Bibliotheken entwickeln, die sie in mehreren verschiedenen Anwendungen einsetzen. Headerdateien dürfen keinen ausführbaren Code, wie z.B. Funktionen enthalten. Jedoch sind Funktionsprototypen erlaubt und genau wie Structs, Unions, Enums, globale Variablen und Makros sehr häufig darin enthalten. So können in einem aufgeteilten Quelltext alle gemeinsamen Komponenten gefunden werden. Dadurch ist es nicht notwendig, den Code einer Funktion, welche in mehreren Quelltextdateien benötigt wird zu kopieren, bzw. neuzuschreiben. Es reicht lediglich, den Prototypen dieser Funktion in eine eigene Headerdatei zu schreiben und diese in die jeweiligen Dateien einzubinden. Dieses Beispiel zeigt die Headerdatei header.h:

#ifndef __HEADER_H__
#define __HEADER_H__
/*Inhalt*/
#endif

Das ist eine Standardkonstruktion in Headerdateien. Zuerst wird abgefragt, ob der Name der Header bereits existiert. Wenn ja, wird der Inhalt eingesetzt, wenn nicht, springt der Präprozessor direkt zum Ende. Es kann nämlich vorkommen, dass eine Header eine andere Header einbindet und so wäre es möglich, dass eine Header zweimal in einer C-Datei vorkäme. Durch das Standardkonstrukt wird überprüft, ob der gleiche Inhalt zuvor schon eingesetzt wurde, um Duplikate zu vermeiden. Ansonsten gäbe es einen Compilerfehler. Die Namensgebung der Symbole ist eigentlich egal. Es hat sich aber durchgesetzt, die Namen groß zu schreiben und den Punkt durch einen Unterstrich zu ersetzen. Üblich sind diese beiden Schreibweisen: HEADER_H HEADER_H

Eine selbstgeschriebene Header muss aber anders eingebunden werden, als eine Headerdatei aus der Standardbibliothek:

#include<stdio.h>
#include"header.h"

Wird die Headerdatei in doppelten Hochkommas geschrieben, sucht der Präprozessor im gleichen Verzeichnis, in dem sich auch die .c-Dateien befinden. Andernfalls sucht er im Verzeichnis der Standardbibliotheken. Befinden sich die Verzeichnisse in einem separaten Ordner, so kann man den Präprozessor explizit in diesem Ordner suchen lassen. Angenommen, das Verzeichnis heißt „lib“, dann stünde folgendes:

#include"lib/header.h"

Werden globale Variablen in Headerdateien definiert, muss man das Schlüsselwort extern davor schreiben. Hier ein Beispiel der Datei main.c:

#include<stdio.h>
 
long _global;
 
int main()
{
    /*...*/
}

Dazu noch die Datei header.h:

#ifndef __HEADER_H__
#define __HEADER_H__
extern long _global;
#endif

So wird dem Compiler dargestellt, dass die Variable _global bereits in einer anderen Datei deklariert wurde und dafür kein weiterer Speicherplatz reserviert werden muss. Würde man extern weglassen, würde es einen Compilerfehler geben, weil doppelte Variablendeklarationen verboten sind.