Forum: Mikrocontroller und Digitale Elektronik Präprozessor


von SeriK (Gast)


Lesenswert?

Ich habe eine Frage zum folgendem Präprozessoranweisungen:

#ifndef _COM_H_
#define _COM_H_

    Code

#endif

Was wird den hier gemacht?

Also falls ein com.h nicht defeniert ist, dann wird esdefiniert und der 
code zwischen define und endif ausgeführt.

Aber wenn die Datei nicht com.h heißt, dann findet er diese sowieso 
nicht.

Kann mir jemand erklären wie sich der Pärprozessor verhält?

Vielen Dank im Voraus.

von 0Fh (Gast)


Lesenswert?

Das ist ein Schutz gegen Mehrfach-Inkludierungen.
Nur wenn der Header "com.h" noch nicht eingebunden ist wird das define 
bekannt gemacht und der Header inkludiert. Ansonsten ist das define 
bereits bekannt und der Header wird nicht nochmal inkludiert. Vorteile 
sind ein schnellerer Präprozessor und übersichtliche *.i Files (Dateien 
in denen defines und Makros bereits ersetzt sind. Braucht man manchmal 
wenn der Code durch Präprozessorverzweigungen unübersichtlich wird.)

von Nico E. (masta79)


Lesenswert?

Die Makros sorgen dafür das ein header nur einmal included wird.

Stell dir vor du hast eine main.c die so anfängt.

#include <wurst.h>
#include <com.h>

in der wurst.h hast du jetzt aber

#include <stdlib.h>
#include <com.h>

Ohne das ifdef Konstrukt von oben würde com.h zwei mal eingesetzt 
werden. Der C-Präprozessor ist sehr stumpfsinnig wenn es um include 
geht.

von Gast (Gast)


Lesenswert?

Hiermit wird verhindert, dass "Code" mehrfach eingefügt wird.
Mit einer Datei com.h hat dies zunächst nichts zu tun.

von Joachim (Gast)


Lesenswert?

Hallo

Du schmeißt da was durcheinander.
COM_H hat erstmal garnichts mit com.h zu tun.

Vielleicht meinst du sowas:

#ifndef COM_H
#define COM_H

#include <com.h>

#endif

Das kannst du verwenden um zu verhindern, das com.h mehrmals
"included" wird.

Gruß
Joachim

von rotuA (Gast)


Lesenswert?

> Was wird den hier gemacht?
Die Anweisungen stammen mit sehr hoher Wahrscheinlichkeit aus einer 
Header-Datei. Header-Dateien können mehrfach in verschiedenen Modulen 
mittels include eingebunden werden. Mehrfach-Einbindungen sind aber 
sinnlos und erzeugen teilweise auch Fehler/Warnungen (Redefinitions 
usw.), außerdem wäre es ja auch doppelter Code. Mit der obigen Anweisung 
wird also nur unnötiger/doppelter Code vermieden.

> Aber wenn die Datei nicht com.h heißt, dann findet er diese sowieso
> nicht.
Verstehe ich nicht. COM_H ist ein frei gewähltes define, welches 
allerdings unbedingt zu einer com.h-Header-Datei gehören sollte, allein 
schon, damit der Code halbwegs verständlich wird. ;-)
Also, es muss nicht zu einer com.h gehören, sollte aber, damit es 
verständlich ist.

> Kann mir jemand erklären wie sich der Pärprozessor verhält?
Hast du doch schon selbst getan.

von SeriK (Gast)


Lesenswert?

Vielen Dank für die Erklärungen.

Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen 
zusammengefasst sind.

In jedem meinem c-File mache includiere ich einfach nur defeines.h
also #include "defines.h"

In jedem .h files mache ich folgendes:

#ifndef COM_H
#define COM_H

Code

#endif

Die Aussage von  Joachim verwirrt mich ein wenig muss ich das so machen:

#ifndef COM_H
#define COM_H

#include <com.h>

#endif

Vielen Dank.

von Mark B. (markbrandis)


Lesenswert?

Wenn die Header-Datei "tralalabums.h" heißt, dann:

#ifndef TRALALABUMS_H

Wenn die Header-Datei "gagga_banana.h" heißt, dann:

#ifndef GAGGA_BANANA_H

Zum Beispiel.

von Karl H. (kbuchegg)


Lesenswert?

SeriK schrieb:

> Die Aussage von  Joachim verwirrt mich ein wenig muss

Du musst gar nichts.

> ich das so machen:
>
> #ifndef COM_H
> #define COM_H
>
> #include <com.h>
>
> #endif

Mach das nicht so.
Der "Include-Guard" (so nennt man eine derartige Sequenz) sollte in die 
Header Datei. Hauptzweck eines Include Guards ist es nicht die 
Compile-Zeit zu verringern, sondern doppelte Deklarationen bzw. 
Redefines zu verhindern.
Nico Erfurth hat weiter oben ja schon gezeigt, wie so etwas entstehen 
kann.

> Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen
> zusammengefasst sind.

Für ein µC-Projekt, welche traditionell eher klein sind, mag so ein 
Rundumschlag angehen.
Aber eigentlich ist das der falsche Weg. Jedes *.c includiert nur 
diejenigen *.h die sie tatsächlich benötigt. Benötigt ein *.h File 
wieder ein anderes *.h, so includiert dieses *.h File seinerseits 
dasjenige *.h welches es benötigt.
Nur so bekommt man eine minimale Make-Hierarchie, bei der make dann auch 
nur tatsächlich diejenigen Teile nachcompiliert, die direkt oder 
indirekt von einem geändertem Header-File abhängen.
Wie gesagt, bei kleinen µC-Projekten mit Komplett-Build-Zeiten von 1 
oder 2 Minuten oder weniger, spielt das untergeordnete Rolle. Wenn der 
Unterschied zwischen einem Komplett-Build und einem Teilbuild allerdings 
in den Bereich Stunden versus Minuten geht, dann macht das einen 
Unterschied.

von rotuA (Gast)


Lesenswert?

> Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen
> zusammengefasst sind.
Warum? defines.h sind oft sinnvoll, aber nicht zum inkludieren von allen 
Headern, sondern für global/projektweit genutzte Defines.

> In jedem meinem c-File mache includiere ich einfach nur defeines.h
> also #include "defines.h"
Das wird nur unübersichtlich werden, in der jeweiligen c-Datei bindet 
man nur die wirklich benötigten Header ein.

> In jedem .h files mache ich folgendes:
Dem Schema solltest du folgen, aber nicht immer COM_H nehmen.
Für test.h nimmst du TEST_H
Für blah.h nimmst du BLAH_H
denn du brauchst für jeden Header einen eigenes Define und um der 
Lesbarkeit Willen, leitest du dass einfach vom Header-Namen ab.
Das musst du aber nur bei selbst erstellten Header-Dateien machen!

> Die Aussage von  Joachim verwirrt mich ein wenig muss ich das so machen:
Mich auch, denn ifdef usw nimmt man im Normalfall im Header.

P.S.: Du brauchst ein gutes C-Buch oder Tutorial, dass sind Grundlagen,
      die du dir einfach selbst erarbeiten musst.

von Peter (Gast)


Lesenswert?

> Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen
> zusammengefasst sind.
Das ist aber nicht gerade sinnvoll. Bei größeren Projekten wird das 
ganze sehr langsam.

von Termite (Gast)


Lesenswert?

Diese konstrukt nennt man auch Codeguard oder IncludeGuards. Sollte 
eigentlich in jede H.Datei rein. (wers nicht macht, handelt sich nur 
probleme ein, oder er weiss genau was er macht)

sie sollen verhindern, das Header Files mehrach in einer 
übersetzungseinheit (c.Datei) eingebunden werden. der Compiler hat 
normalerweise danach seine kleineren bis grösseren probleme, wenn der 
Inhalt der H.Dateien mehrfach in der übersetzungseinheit vorkommt. 
Redefinition fehler / Warnungen, ...

auserdem kann es bei hässlichen include construktionen dazu führen, das 
man include schleifen baut. (z.B. durch gegenseitiges includieren über 5 
Ecken) was dazu führen kann, das der code sich so erst gar nicht 
übersetzen lässt. normalerweise mekert der compiler mit irgend einer 
abstrakten fehlermeldung von wegen include und schleifen und so, oder 
schmirt ganz einfach nur weg, weil im der speicher aus geht.

Ein Präprozessor ist eigentlich ein Dummes programm, er ersetzt nur alle 
angegebenen #defines #includes durch die angegebenen inhalte. beim 
inlcude halt durch den inhalt der angegebenen Datei. Dadurch kann man 
oft benötigte Definitonen, und Declarationen (Funktionen, Globale 
Variablen) in einer separaten Datei pflegen. Und muss sie nicht in jeder 
Übersetzungseihneit separat einpflegen (wartungsaufwendig und 
fehleranfällig)

von Termite (Gast)


Lesenswert?

nochwas

es gibt bei manchen leuten / projekten die anforderung, das H.dateien 
sich fehlerfrei übersetzen lassen müssen wenn man diese an den 
C-Compiler alleine übergibt. Auch wenn dabei kein bincode dabei 
rauskommt, garantiert dies doch, das alle in der H.Datei notwengien 
Includes enthalten sind.

Erleichtert auch den umgang z.B. mit einer lib. man muss nicht erst 5 
andere h.Dateien includieren (z.B. win API), damit die lib endlich 
funktioniert.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.