Forum: Mikrocontroller und Digitale Elektronik Wozu dient solch eine #ifndef -Anweisung?


von Stephan (Gast)


Lesenswert?

1
#ifndef _PCF8574_H
2
#define _PCF8574_H
3
4
#include <avr/io.h>
5
6
void pcf8574_init (void);
7
void pcf8574_send_stop (void);
8
9
#endif

...wenn doch jede .c Datei einzeln kompiliert wird? Wird das 
"definiert-sein" irgendwo anders noch abgefragt?

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
> ...wenn doch jede .c Datei einzeln kompiliert wird?

a.c -> includiert b.h
b.h -> includiert c.h

c.h -> includiert d.h
b.h -> incluidert d.h

schon ist d.h 2mal drin.

von jmp (Gast)


Lesenswert?

Das ist ein Include-Guard das verhindert, dass eine .h mehrfach included 
wird:
http://de.wikipedia.org/wiki/Include-Guard

--jmp

von Hugo Boss (Gast)


Lesenswert?

ganz einfach, stell Dir mal vor, Du bindest die Headerdatei zweimal ein, 
einmal in Modul 1 und dann in Modul 2.

Hast Du ein Programm mit beiden Modulen, dann würde die selbe 
Headerdatei zweimal eingebunden und es kommt zu 
Fehlermeldungen/Warnungen wegen doppelter Namensvergabe.

Also bedient man sich eines Tricks, man definiert eine Konstante und mit

äifndef -> if not defined

wird dann geprüft, ob die define-Anweisung schon existiert, dann wird 
die Anweisung innerhalb des Blocks

#ifndef


...


#endif

abgearbeitet, ansonsten nicht.

von asdf (Gast)


Lesenswert?

Das verhindert einfach doppelt Deklarationen, falls die Datei mehrfach 
eingebunden wird.

von Sebastian H. (sebihepp)


Lesenswert?

Eigentlich sollte sowas in einer Header-Datei stehen.

Jedenfalls verhindert es Fehler. (Wegen Mehrfachdeklaration) Das kann 
z.B. passieren, wenn man mehrere Headerdateien einbindet, die wiederum 
eine bestimmte Header-Datei einbinden.

Edit: Da war jemand schneller

: Bearbeitet durch User
von Stephan (Gast)


Lesenswert?

Das macht alles irgendwie Sinn.

Aber warum ist es denn unkritisch, in jeder .c Datei ein
1
 #include <avr/io.h>
 einzubauen? Wo ist der Unterschied?

von Borislav B. (boris_b)


Lesenswert?

Die coolen leute benutzen das aber nicht mehr.
Die nehmen "#pragma once" ;-)

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

in der Datei avr/io.h steht höchstwahrscheinlich am Anfang genau so eine 
#ifndef-Anweisung, die überprüft ob avr/io.h schon einmal eingebunden 
wurde oder nicht.
Wenn sie bereits eingebunden wurde wird der folgende Block (also alles, 
was zwischen #ifndef und #endif steht) einfach übersprungen.

von Stephan (Gast)


Lesenswert?

Thomas schrieb:
> in der Datei avr/io.h steht höchstwahrscheinlich am Anfang genau so eine
> #ifndef-Anweisung, die überprüft ob avr/io.h schon einmal eingebunden
> wurde oder nicht.

WOW! Das ist es. Natürlich! Ich Depp!
Mehr Zucker ins Kaffee!
Danke an alle!

von Thomas E. (thomase)


Lesenswert?

Hugo Boss schrieb:
> ganz einfach, stell Dir mal vor, Du bindest die Headerdatei zweimal ein,
> einmal in Modul 1 und dann in Modul 2.
Module? Module sind in C einzelne Funktionen. Was hat eine Funktion mit 
einer Headerdatei zu tun?
1. In Funktionen werden keine Headerdateien eingebunden
2. Wenn eine Funktion zweimal vorhanden ist, hat man ein ganz anderes 
Problem

mfg.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Thomas Eckmann schrieb:
> Module? Module sind in C einzelne Funktionen. Was hat eine Funktion mit
> einer Headerdatei zu tun?

Nö, als Module werden sogenannte "translation units" bezeichnet.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Im Übrigen sind Bezeichner, die mit einem Unterstrich gefolgt von einem
Großbuchstaben oder einem weiteren Unterstrich beginnen, grundsätzlich
reserviert für Compiler und (System-)Bibliothek.

In einem von einem Anwender gezimmerten Headerfile hat also ein
Bezeichner wie _PCF8574_H nichts verloren.  Stattdessen wählt man besser
die (offenbar zu einfach anmutende :) Variante PCF8574_H.

von Thomas (Gast)


Lesenswert?

Boris P. schrieb:
> Die coolen leute benutzen das aber nicht mehr.
> Die nehmen "#pragma once" ;-
1
 #pragma once

führt bei mir zu folgender Fehlermeldung:

error in line 23: non portable pragma conversation

von Borislav B. (boris_b)


Lesenswert?

Thomas schrieb:
> error in line 23: non portable pragma conversation

Was für einen Compiler benutzt du denn? Alle gängigen sollten damit klar 
kommen...

Clang                   Supported[5]
Comeau C/C++           Supported[6]
C++Builder XE3           Supported[7]
Digital Mars C++   Supported[8]
GCC                   Supported[9] (since 3.4[10])
Intel C++ Compiler   Supported[11]
Microsoft Visual C++   Supported[12]
Pelles C           Supported[13]
ARM DS-5           Supported[14]
IAR C/C++           Supported[15]

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andererseits?  Wofür ein Pragma (was nun mal per definitionem nicht
portabel ist), wenn es mit dem idempotency ifdef seit Jahrzehnten auch
mit ganz gewöhnlichen Bordmitteln geht, die noch dazu 
rückwärtskompatibel
bis zur Jungsteinzeit sind?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> rückwärtskompatibel bis zur Jungsteinzeit

Das ist uncool. Das könnte ja auch mit Compilern übersetzt werden, die 
kein C11 oder auch nur C99 unterstützen.

von Karl H. (kbuchegg)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Jörg Wunsch schrieb:
>> rückwärtskompatibel bis zur Jungsteinzeit
>
> Das ist uncool.

Genau.
Da müsste sich ja der geneigte Jungprogrammierer ein Schema einfallen 
lassen, wie er die Makronamen bildet.

Im Ernst: ok, so ein #pragma hat schon seine Vorteile, wenn man 
Codegeneratoren schreibt. Auf der anderen Seite ist ein #pragma genau 
das: eine Möglichkeit, wie man Compilerspezialitäten unterbringen kann. 
#pragma ist zuallererst per Definition nicht portabel.

von Rolf Magnus (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Jörg Wunsch schrieb:
>> rückwärtskompatibel bis zur Jungsteinzeit
>
> Das ist uncool. Das könnte ja auch mit Compilern übersetzt werden, die
> kein C11 oder auch nur C99 unterstützen.

Ja, und es könnte dann auch mit Compilern übersetzt werden, die zwar C11 
oder C99 unterstützen, aber diese proprietäre Erweiterung nicht.

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.