Hallo!
Ich habe gerade in AtmelStudio 6.1 (Simulator) mit Mehrfacheinbindungen
experimentiert und festgestellt, dass der Compiler nicht mekert, wenn
eine Mehrfacheinbindung vorliegt.
Datei “a.h“
struct foo
{
int member;
};
Datei “b.h“
#include "a.h"
Datei “c.h“
#include "a.h"
#include "b.h"
In der Datei “c.h“ wurde “a.h“ über “b.h“ doppelt eingebunden.
Kann es sein, dass der Compiler (Omptimierung wurde deaktiviert) eine
Mehrfacheinbindung automatisch erkennt und keine Fehlermeldung ausgibt?
Eine Mehrfacheinbindung ist aus Compilersicht erst einmal per se nicht verboten. Ob sie sinnvoll ist oder nicht, hängt ausschließlich vom Inhalt deiner Headerdatei selbst ab; es gibt sogar Headerdateien in der Standardbibliothek, für die Mehrfacheinbindungen explizit sinnvoll sind (<assert.h>). Insbesondere jedoch, wenn eine Headerdatei #define-Anweisungen enthält, sollte sie sich gegen Mehrfacheinbindung absichern, denn mehrere #defines führen zumindest zu einer Warnung. Das hat mit „Atmel Studio x.y.z“ übrigens rein überhaupt nichts zu tun.
S. Lonci schrieb: > Kann es sein, das der Compiler (Omptimierung wurde deaktiviert) eine > Mehrfacheinbindung automatisch erkennt und keine Fehlermeldung ausgibt? Wenn schon, dann hat er eher festgestellt, dass deine Doppelte struct Definition in allen Punkten in beiden Fällen übereinstimmt, und deshalb spart er sich eine Fehlermeldung, weil ja dann ganz offensichtlich ohnehin nichts schlimmes passieren kann. Aber einen #include kann der Präprozessor (der behandelt includes) nicht einfach ignorieren.
S. Lonci schrieb: > Kann es sein, dass der Compiler (Omptimierung wurde deaktiviert) eine > Mehrfacheinbindung automatisch erkennt und keine Fehlermeldung ausgibt? Ich sag mal so: Es wird einen Grund haben, warum in einer Headerdatei (in diesem Fall: test_header.h), die du über Atmel Studio erzeugst drin steht:
1 | #ifndef TEST_HEADER_H_
|
2 | #define TEST_HEADER_H_
|
3 | |
4 | |
5 | #endif /* TEST_HEADER_H_ */ |
Und der Grund ist bestimmt nicht, weil irgendeinem Programmierer langweilig war und er das da aus spaß reingebaut hat... Schalte mal -Wall -Wextra -Werror ein, vielleicht sieht das dann schon anders aus. Und das ganze hat auch nichts mit den optimierungs einstellungen zu tun.
Eine Frage habe ich noch zur Schreibweise: Warum schreibt man #ifndef B_H_ und nicht #ifndef b.h ?
1 | #ifndef B_H_
|
2 | #define B_H_
|
3 | |
4 | #include "a.h" |
5 | |
6 | #endif
|
S. Lonci schrieb: > und nicht #ifndef b.h ? > Probiers halt einfach aus, ob du in einem Preprozessor Makro einen Punkt im Makronamen benutzen kannst. Denk auch drann: Ein makro ist im Reglfall ja kein Selbstzweck. Ok, der Fall Include Guards ist ein bischen anders gelagert, aber im Regelfall wird ja ein Makro auch irgendwo im Programmtext verwendet. Machst du dir jetzt ein
1 | #define TEST.X var
|
und verwendest das
1 | int main() |
2 | {
|
3 | int var; |
4 | |
5 | TEST.X = 5; |
6 | }
|
was wird dann wohl passieren? Das ist zwar immer eine Gratwanderung und komplexere Sachverhalte kann man damit eher schlecht ergründen. Aber viele einfache Dinge kann man tatsächlich einfach ausprobieren und aus der Fehlermeldung des Compilers seine Schlüsse ziehen. Hat man mehrere Compiler zur Verfügung, dann kann man auch mal vergleichen, wie ein und derselbe Fehler zu unterschiedlichen Fehlermeldungen (im Wortlaut verschieden) führt. Das ist ganz hilfreich, sich da auch eine gewisse Praxis anzueignen, um aus Fehlermeldungen die richtigen Schlüsse zu ziehen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.