Wie deklariere ich eine Struktur in einem Header, die von mehreren Dateien in c verwendet werden soll?

Lesezeit: 7 Minuten

Wenn ich eine source.c-Datei mit einer Struktur habe:

struct a { 
    int i;
    struct b {
        int j;
    }
};

Wie kann diese Struktur in einer anderen Datei (z func.c)?

Sollte ich eine neue Header-Datei erstellen, deklariere die Struktur dort und füge diesen Header hinzu func.c?

Oder sollte ich die gesamte Struktur in einer Header-Datei definieren und diese in beide aufnehmen source.c und func.c? Wie kann die Struktur deklariert werden extern in beiden Dateien?

Sollte ich typedef es? Wenn das so ist, wie?

  • Beachten Sie, dass die Strukturdefinition kein gültiges C ist. Nach der schließenden Klammer für sollte mindestens ein Semikolon stehen struct baber dann Ihre Struktur a deklariert einen Typ, der nicht verwendet wird (vielleicht sollten Sie einen Mitgliedsnamen definieren knach der inneren geschlossenen Klammer und vor dem Semikolon.

    – Jonathan Leffler

    30. September 2014 um 23:57 Uhr

Benutzeravatar von paercebal
paercebal

wenn diese Struktur von einer anderen Datei func.c verwendet werden soll, wie geht das?

Wenn ein Typ in einer Datei verwendet wird (dh in der Datei func.c), muss er sichtbar sein. Der schlechteste Weg, dies zu tun, ist das Kopieren und Einfügen in jede benötigte Quelldatei.

Der richtige Weg besteht darin, es in eine Header-Datei zu packen und diese Header-Datei bei Bedarf einzuschließen.

Sollen wir eine neue Header-Datei öffnen und die Struktur dort deklarieren und diesen Header in die func.c aufnehmen?

Dies ist die Lösung, die ich mehr mag, weil sie den Code sehr modular macht. Ich würde Ihre Struktur wie folgt codieren:

#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

#endif

Ich würde Funktionen, die diese Struktur verwenden, in denselben Header einfügen (die Funktion, die “semantisch” Teil ihrer “Schnittstelle” ist).

Und normalerweise könnte ich die Datei nach dem Strukturnamen benennen und diesen Namen erneut verwenden, um die Header Guards-Definitionen auszuwählen.

Wenn Sie eine Funktion mit einem Zeiger auf die Struktur deklarieren müssen, benötigen Sie nicht die vollständige Strukturdefinition. Eine einfache Forward-Deklaration wie:

struct a ;

Wird ausreichen, und es verringert die Kopplung.

oder können wir die Gesamtstruktur in der Header-Datei definieren und diese sowohl in source.c als auch in func.c einfügen?

Dies ist ein anderer Weg, etwas einfacher, aber weniger modular: Code, der nur Ihre Struktur benötigt, um zu funktionieren, müsste immer noch alle Typen enthalten.

In C++ könnte dies zu interessanten Komplikationen führen, aber das gehört nicht zum Thema (kein C++-Tag), daher gehe ich nicht näher darauf ein.

dann wie man diese Struktur in beiden Dateien als extern deklariert. ?

Ich verstehe den Sinn vielleicht nicht, aber Greg Hewgill hat eine sehr gute Antwort in seinem Beitrag Wie deklariere ich eine Struktur in einem Header, der von mehreren Dateien in c verwendet werden soll?.

Sollen wir es dann wie eingeben?

  • Wenn Sie C++ verwenden, tun Sie dies nicht.
  • Wenn Sie C verwenden, sollten Sie.

Der Grund dafür ist, dass die Verwaltung von C-Strukturen mühsam sein kann: Sie müssen das Schlüsselwort struct überall dort deklarieren, wo es verwendet wird:

struct MyStruct ; /* Forward declaration */

struct MyStruct
{
   /* etc. */
} ;

void doSomething(struct MyStruct * p) /* parameter */
{
   struct MyStruct a ; /* variable */
   /* etc */
}

Während ein Typedef es Ihnen ermöglicht, es ohne das Schlüsselwort struct zu schreiben.

struct MyStructTag ; /* Forward declaration */

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

void doSomething(MyStruct * p) /* parameter */
{
   MyStruct a ; /* variable */
   /* etc */
}

es ist wichtig Sie behalten immer noch einen Namen für die Struktur. Schreiben:

typedef struct
{
   /* etc. */
} MyStruct ;

erstellt nur eine anonyme Struktur mit einem typdefinierten Namen, und Sie können ihn nicht vorwärts deklarieren. Halten Sie sich also an das folgende Format:

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

Daher können Sie MyStruct überall dort verwenden, wo Sie das Hinzufügen des Schlüsselworts struct vermeiden möchten, und MyStructTag trotzdem verwenden, wenn eine Typedef nicht funktioniert (dh Vorwärtsdeklaration).

Bearbeiten:

Korrigierte falsche Annahme über die C99-Strukturdeklaration, wie zu Recht von Jonathan Leffler bemerkt wurde.

Bearbeiten 01.06.2018:

Craig Barnes erinnert uns in seinem Kommentar daran, dass Sie keine separaten Namen für den „tag“-Namen der Struktur und ihren „typedef“-Namen verwenden müssen, wie ich es oben der Übersichtlichkeit halber getan habe.

Tatsächlich könnte der obige Code gut geschrieben werden als:

typedef struct MyStruct
{
   /* etc. */
} MyStruct ;

IIRC, das ist eigentlich das, was C++ mit seiner einfacheren Struct-Deklaration hinter den Kulissen macht, um es mit C kompatibel zu halten:

// C++ explicit declaration by the user
struct MyStruct
{
   /* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;

Zurück zu C, ich habe beide Verwendungen gesehen (getrennte Namen und gleiche Namen), und keine hat Nachteile, die ich kenne, also macht die Verwendung des gleichen Namens das Lesen einfacher, wenn Sie C keine separaten “Namespaces” für Strukturen und andere Symbole verwenden .

  • Können Sie den Abschnitt des C99-Standards kommentieren oder darauf hinweisen, der Ihren Kommentar “Wenn Sie C99 verwenden, nicht” rechtfertigt?

    – Jonathan Leffler

    26. November 2008 um 7:53 Uhr

  • Sie haben Recht. Ich habe kürzlich einen C99 getestet und war überrascht zu sehen, dass meine nicht typisierte Struktur nicht erkannt wurde, wenn sie auf C++-Weise verwendet wurde. Ich habe nach Compiler-Optionen gesucht und dann in allen Standarddokumenten, die ich anfassen konnte, aber nichts gefunden, was erklären könnte, dass ich es für möglich hielt …

    – Paercebal

    30. November 2008 um 20:07 Uhr

  • … Also trotzdem danke für den Hinweis. Ich habe es gleich korrigiert.

    – Paercebal

    30. November 2008 um 20:10 Uhr

  • Es besteht keine Notwendigkeit, unterschiedliche Namen für die zu verwenden struct Etikett und die typedef Name. C verwendet einen anderen Namensraum für struct Tags, damit Sie verwenden können MyStruct für beide.

    – Craig Barnes

    31. Mai 2018 um 8:02 Uhr

  • @CraigBarnes Du hast Recht, aber ich wollte, dass das klar wird, indem ich einfach den Code lese. Hätte ich denselben Namen angegeben, hätte dies C-Neulinge verwirren können, weil sie den Namen zweimal in dieselbe „Erklärung“ schreiben müssen. Ich werde eine Notiz hinzufügen, in der Ihr Kommentar erwähnt wird. Danke!

    – Paercebal

    1. Juni 2018 um 8:58 Uhr

Benutzeravatar von Greg Hewgill
Greg Hewgill

Für eine Strukturdefinition, die über mehr als eine Quelldatei hinweg verwendet werden soll, sollten Sie diese unbedingt in eine Header-Datei packen. Fügen Sie dann diese Header-Datei in jede Quelldatei ein, die die Struktur benötigt.

Das extern Die Deklaration wird nicht für Strukturdefinitionen verwendet, sondern für Variablendeklarationen (d. h. einige Datenwerte mit einem von Ihnen definierten Strukturtyp). Wenn Sie dieselbe Variable in mehr als einer Quelldatei verwenden möchten, deklarieren Sie sie als extern in einer Header-Datei wie:

extern struct a myAValue;

Dann in eines Quelldatei, definieren Sie die eigentliche Variable:

struct a myAValue;

Wenn Sie dies vergessen oder versehentlich in zwei Quelldateien definieren, werden Sie vom Linker darauf hingewiesen.

  • Möglicherweise erhalten Sie einen Linker-Fehler oder auch nicht. In C ermöglicht das Verknüpfungsmodell „gemeinsame“ Definitionen, sodass mehrere Definitionen ohne Initialisierer (und möglicherweise mit demselben Initialisierer) funktionieren können. Es ist eine ‘gemeinsame Erweiterung’. Ich glaube, einige Compiler unterstützen auch vorläufige (fehlende) Definitionen.

    – Jonathan Leffler

    23. Oktober 2008 um 6:12 Uhr

  • Dann, in einer Quelldatei, definieren die eigentliche Variable: ; … oder aus Versehen definieren es in zwei Quelldateien … 🙂

    – Johannes Schaub – litb

    25. November 2008 um 19:34 Uhr

  • Eine Technik, die ich für das Deklarieren/Definieren-Problem verwendet habe, ist das bedingte Definieren GLOBAL wie extern oder nichts oben im Header und deklarieren Sie dann Variablen als GLOBAL struct a myAValue;. Aus den meisten Quelldateien arrangieren Sie die #define GLOBAL extern zu verwendende Version (erklären die Variablen) und von genau einer Quelldatei bewirkt, dass die leere Definition verwendet wird, damit die Variablen verwendet werden definiert.

    – TripeHound

    18. März 2014 um 16:37 Uhr

  • Sie können den Strukturnamen mit dem Typedef-Namen in C identisch haben, aber nicht in C++.

    – xuhdev

    27. Juni 2014 um 5:46 Uhr

Benutzeravatar von fmsf
fmsf

Ah:

#ifndef A_H
#define A_H

struct a { 
    int i;
    struct b {
        int j;
    }
};

#endif

Los geht’s, jetzt müssen Sie nur noch ah in die Dateien einfügen, in denen Sie diese Struktur verwenden möchten.

1423350cookie-checkWie deklariere ich eine Struktur in einem Header, die von mehreren Dateien in c verwendet werden soll?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy