www.mikrocontroller.net

Forum: Compiler & IDEs Struktur extern deklarieren


Autor: Nixwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe eine Struktur foo in einem .c-File erstellt und eine 
entsprechende Variable bar definiert:

struct foo {int a; int b;};
...
struct foo bar;

Nun möchte ich bar in einem Header-File extern deklarieren.

Genügt es, zu schreiben:

extern struct foo bar;  ?

Der Compiler bringt zumindest keinen Fehler.

Oder sollte der Compiler den Aufbau der Struktur wissen, so dass ich die 
Typdefinition auch noch in die externe Deklaration mit hinein nehmen 
muss?

Ich weiß dass es besser wäre, die Typdefinition in das Header-File zu 
schreiben und im C-File nur die Variable zu definieren, aber das ist 
aufgrund des Anwendungsfalls nicht möglich.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nixwisser wrote:

> Genügt es, zu schreiben:
>
> extern struct foo bar;  ?
>
> Der Compiler bringt zumindest keinen Fehler.
>
> Oder sollte der Compiler den Aufbau der Struktur wissen, so dass ich die
> Typdefinition auch noch in die externe Deklaration mit hinein nehmen
> muss?

Das hängt davon ab, was du damit hernach anstellen willst.

Vom logischen Standpunkt: solange der Compiler keinen Speicher für
bar außerhalb anlegen muss und solange er nicht auf dessen Elemente
zugreifen muss, geht das.

In C-Standardsprache gefasst heißt das, du hast eine unvollständige
Typdeklaration für struct foo.  Letztlich beschränkt sich dadurch
das, was du mit dem Objekt bar anstellen kannst darauf, dass du dessen
Adresse bilden kannst und diese bspw. an eine Funktion weiterreichen
oder mit einem Zeiger (der auf eine Element vom Typ struct foo zeigt)
auf Gleichheit testen.

Autor: Nixwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf die Elemente von bar wird aber zugegriffen, und zwar bevor bar 
definiert wird. Warum gibt der Compiler dann keine Fehlermeldung aus?

Die Übersetzungseinheit würde nach Inkludierung so aussehen:

extern struct foo bar; (aus h-File)
...
struct foo {int a; int b}; (c-File)
...
bar.a = 1; (c-File)

bar wird in einem anderen c-File definiert.

Ist der Compiler so schlau, die Typdefinition von struct foo 
nachträglich mit der externen Deklaration von bar im Header zu 
verbinden?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nixwisser wrote:

> Ist der Compiler so schlau, die Typdefinition von struct foo
> nachträglich mit der externen Deklaration von bar im Header zu
> verbinden?

Ist ja nicht "nachträglich": er hat die Definition des Typs gesehen,
bevor er das erste Mal auf ein Element von bar zugreifen musste.
Damit ist alles in Butter, er hat zu diesem Zeitpunkt die notwendigen
Informationen beisammen gehabt.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, in diesem Falle wird die externe Deklaration mit der 
darauffolgenden überschrieben.


struct foo {int a; int b};

gehört nicht in ein C-File, sondern in eine Headerdatei.
Und zwar vor die Deklaration

extern struct foo bar;

Autor: Nixwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ist ja nicht "nachträglich": er hat die Definition des Typs gesehen,
>bevor er das erste Mal auf ein Element von bar zugreifen musste.
>Damit ist alles in Butter, er hat zu diesem Zeitpunkt die notwendigen
>Informationen beisammen gehabt.

Das ist schon richtig, aber er die Variable wurde extern deklariert, 
bevor der angegebene Typ "struct foo" definiert wurde. Ist das kein 
Problem?

>Nein, in diesem Falle wird die externe Deklaration mit der
>darauffolgenden überschrieben.

Also der Compiler legt sich in seinen Tabellen eine externe Variable bar 
vom Typ struct foo ab, und struct foo wird dann durch struct foo{int a; 
int b;}
überschrieben?

>struct foo {int a; int b};
>
>gehört nicht in ein C-File, sondern in eine Headerdatei.
>Und zwar vor die Deklaration

Wie ich schon geschrieben habe, ist das nicht möglich (an dem c-File 
darf ich nicht drehen, nur Code "drumherum" bauen)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie ich schon geschrieben habe, ist das nicht möglich (an dem c-File
> darf ich nicht drehen, nur Code "drumherum" bauen)

Dann musst Du pfuschen. Und die Deklaration des Strukturtyps trotzdem 
in die Headerdatei packen. Denn da gehört sie hin; wenn der Vollpfosten, 
der die C-Datei verbrochen hat, den Strukturtyp lokal definiert und 
trotzdem externen Zugriff darauf haben möchte, dann sollte er solange 
mit Ausgaben des K&R beworfen werden, bis er's einsieht.

Autor: Nixwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Dann musst Du pfuschen. Und die Deklaration des Strukturtyps trotzdem
>in die Headerdatei packen.

Meldet der Compiler dann nicht eine Typ-Neudefinition?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nixwisser wrote:

> Das ist schon richtig, aber er die Variable wurde extern deklariert,
> bevor der angegebene Typ "struct foo" definiert wurde. Ist das kein
> Problem?

Deklarationen sind Schall und Rauch. ;-)  Formal ist das Ding halt
erst einmal mit einem unvollständigen Struturtyp deklariert.  Das
ist aber trotzdem eine gültige Deklaration, da man ja vom entsprechenden
Objekt ggf. eine Adresse ermitteln kann (die dann auf den Typ struct
foo zeigt, dessen Details dem Compiler nicht bekannt sein müssen).

Wenn der Strukturtyp dann selbst noch deklariert wird, besitzt der
Compiler die notwendige komplette Deklaration, um auch auf die
Elemente von bar zugreifen zu können.

Zwar unüblich aber legal.

> Also der Compiler legt sich in seinen Tabellen eine externe Variable bar
> vom Typ struct foo ab,

Er merkt sich erstmal nur, dass er sie gesehen hat, dass es eine
struct-Variable ist, aber dass der Typ unvollständig ist, sodass
sie nur eingeschränkt benutzbar ist.

> und struct foo wird dann durch struct foo{int a;
> int b;}
> überschrieben?

Nicht ,überschrieben', sondern ,vervollständigt'.

Autor: Nixwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verstehe, danke.

Ich hatte es zuvor mit einem typedef auf den Strukturtyp versucht. 
Diesen konnte ich der extern Deklaration aber nicht verwenden. Ich nehme 
mal an, dass liegt daran dass der Typ dem Compiler beim parsen der 
extern Deklaration nicht bekannt ist (die Typendefinition kommt ja erst 
später im c-File).

Er braucht also zumindest einen "halben" Typ? ;)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nixwisser wrote:

> Er braucht also zumindest einen "halben" Typ? ;)

Ja, er muss wissen, dass es eine struct ist und braucht den Namen der
struct auch noch, um sie ggf. zuordnen zu können.  Durch diese
Möglichkeit lassen sich bspw. gegenseitig referenzierende Listen
implementieren:
struct foo;
struct bar;

struct foo {
  struct bar *barp;
  int foodata;
};

struct bar {
  struct foo *foop;
  int bardata;
};

Zu dem Zeitpunkt, da von struct bar ein Zeiger benutzt werden soll,
ist über sie noch nichts weiter bekannt als ihr Name, aber das genügt
für den Zweck.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.