.c oder .h bei include?

Cusco

Erfahrenes Mitglied
Hi,

schon wieder ich. Was ist genau der Unterschied für den Compiler mit einer .c (CSource) und .h (CHeader) ich bin aus meinen Buch nicht so recht schlau geworden.

Bei größeren Projekten muss der Source ja zwangsläufig in mehere Dateien aufgeteilt werden. Aber von Hauptsource mal abgesehen, in was speichert man die Zusatzdateien? in .c oder auch als .h? Was ist von vorteil, bzw der Unterschied?
 
Hi!

Ich versuch das mal als Übung zu sehen.
Ich habe mich in den letzten Wochen in C eingearbeitet und über eine Auflistung, was in einen Header gehört, bin ich zwar nicht gestoßen, meine aber dennoch den Sinn verstanden zu haben.
Um das zu überprüfen jetzt mal mein Post. :)

In eine Header-Datei kommt generell kein ausführbarer Code.
Stattdessen findet man darin Deklarationen und Präcompileranweisungen.

Das hat den Sinn, dass verschiedene C-Quellen auf eine Funktion zugreifen können, die nur eine der Quellen implementiert hat.
Du kannst also eine Funktion in der Quelle eins.c schreiben und ihre Deklaration in den Header eins.h schreiben. Deine Quelle zwei.c bindet den Header eins.h ebenfalls ein und kann dann die Funktion aus eins.c benutzen, ohne zu wissen, was sie macht. Nur was man ihr übergeben muss und was man zurück erhält (also die Typen) sind bekannt.
So kann man dann eins.c und zwei.c kompilieren.
Man muss aber beide Objektdateien (eins.o und zwei.o) zusammen linken, denn sonst bemerkt der Linker bei zwei.o "Oh, ich soll hier irgendwo eine Funktion finden, aber ich seh keine" und bricht ab. ;)
Ausführbarer Code hingegen gehört immer in die Quelldateien, denn wenn man z.B. eine Variable im Header eins.h deklariert, wird es beim Linken zu einem Fehler kommen, weil die Headerdatei zweimal eingebunden wird und die Variable daher doppelt existiert. Das gleiche gilt für die Implementation von Funktionen.

Die Headerdateien dienen also als Interface während die C-Quellen die Implementation darstellen.
Man kann zwar per #include auch C-Quellen einbinden, aber eigentlich sollte man nur Header-Dateien einbinden.
Die C-Quellen kommen beim Linken zusammen.

Beispiel:
eins.h:
Code:
#include <stdio.h>
#include <string.h>

void eineFunktion(int i);
eins.c:
Code:
#include "eins.h"

void eineFunktion(int i)
{
  printf("%s\n",i+1);
}
zwei.c:
Code:
#include "eins.h"

int main(int argc, char** argv)
{
  eineFunktion(3);
  return 0;
}


Ich bin mir ziemlich sicher, dass Header-Dateien für 1000 weitere Dinge gut sind (Typdefinitionen so'n Zeug und sicherlich noch Sachen, von denen ich noch nie gehört habe), aber ich meine, damit den Grundgedanken von Header-Dateien getroffen zu haben.
Falls dem nicht so ist, korrigiert mich bitte. :)
 
Hi. (schon wieder ich ;))

In die Header Dateien gehören ausschließlich Deklarationen von Variablen und Funktionen - keine Definitionen.

Eine Header Datei wird als allererstes (wenn sie von einer .c Quelldatei durch ein #include referenziert wird) an der Stelle wo das #include steht eingesetzt. Das passiert in der Präprozessor-Phase. Der Präprozessor expandiert die Präprozessorvariablen und -makros, setzt die Header Dateien ein und liefert am Ende eine "vorgekaute" C Datei für den C-Compiler.

Das Problem warum man nur Deklarationen in Header Dateien schreiben darf ist, das mehrere C Dateien die gleiche Header Datei verwenden können. Beide C Dateien werden getrennt voneinander zu jeweils einer Objektdatei kompiliert. Ist in der Header Datei dann z.B. eine Funktion definiert erhalten beide Objektdateien eine (kompilierte) Version dieser Funktion. Bei der dritten Phase der Übersetzung, dem Linken, gibt es dann ein Problem weil der Linker auf 2 Funktionen mit gleichem Namen trifft was dann zu einem Fehler führt.

Außerdem sollte man Header Dateien immer gegen Mehrfach-includes schützen:
Code:
/* Header Datei "text_utils.h" */
#ifndef TEXT_UTILS_H
#define TEXT_UTILS_H

/* Deklarationen */

int extract (const char*);

extern int text_utils_error;

#endif

Dann in der dazugehörenden .c Datei werden die Funktionen bzw. Variablen definiert, so dass im gesamten Programm (nachher beim Linken) nur eine Instanz von jedem "Objekt" existiert.

Code:
 /* Datei text_utils.c */

#include "text_utils.h"

int extract (const char* xyz) {
  ...
}

int text_utils_error;

Andere Dateien müssen dann nur die text_utils.h einbinden um dem Compiler die Funktionen und Variablen (die in text_utils.c definiert sind) bekannt zu machen und können dann benutzt werden.
Code:
/* Datei main.c */

#include "text_utils.h"

...
  int i = extract ("ksd 94949 kkdidk k4k");

  if (text_utils_error != 0) /* ups, Fehler? */
    ...

Gruß

/edit: Oh, da war jemand schneller. Naja, doppelt hält besser ;)
 
Zuletzt bearbeitet:
Also damit ich das Verstehe muss es z.B. so aussehen, mir geht es vorallem um Globale Variablen.

Code:
#include <standart.h>

char Test[]="test";
...

#include "eigenen.c"

main{}

Nun ist die Variable "Test" auch in der eigenen.c gültig um da z.B. in Funktionen nutzen zu können, bindet man .h ein ist das nicht der Fall oder? Und eine Funktion von der eigenen.c kann in main() aufgerufen werden?
 
Zuletzt bearbeitet:
Cusco hat gesagt.:
Also damit ich das Verstehe muss es z.B. so aussehen, mir geht es vorallem um Globale Variablen.

Code:
#include <standart.h>

char Test[]="test";
...

#include "eigenen.c"

main{}

Nun ist die Variable "Test" auch in der eigenen.c gültig um da z.B. in Funktionen nutzen zu können, bindet man .h ein ist das nicht der Fall oder? Und eine Funktion von der eigenen.c kann in main() aufgerufen werden?
Also irgendwie verstehe ich das jetzt nicht so ganz. Aber man bindet keine .c Dateien mit #include ein.

Deine Variablendefinition von Test gehört nicht in eine Header Datei. Kuck dir in deinem Buch mal das Schlüsselwort extern an (oder schau wie ich es oben gemacht hab).

/edit: Ich glaub jetzt weiß ich eher was du meinst. Damit die Variable in main.c als auch in eigenen.c benutzt werden kann solltest du die Variable in einer Header Datei die von beiden .c Dateinen eingebunden wird deklarieren und zwar extern. In einer ausgewählten .c Datei (meinetwegen in main.c) definierst du dann die Variable Test so wie es da steht.

Gruß
 
Zuletzt bearbeitet:
Zurück