it-swarm.com.de

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

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 verwendet werden (d. H. func.c)?

Soll ich eine neue Header-Datei erstellen, die Struktur dort deklarieren und diesen Header in func.c Einfügen?

Oder sollte ich die gesamte Struktur in einer Header-Datei definieren und diese sowohl in source.c Als auch in func.c Einfügen? Wie kann die Struktur in beiden Dateien als extern deklariert werden?

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

110
Manoj

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

Wenn ein Typ in einer Datei (d. H. Func.c-Datei) verwendet wird, muss er sichtbar sein. Der schlechteste Weg, dies zu tun, ist das Kopieren und Einfügen in jede Quelldatei, die es benötigt.

Der richtige Weg ist, es in eine Header-Datei einzufügen 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 kodieren:

#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 setzen (die Funktion, die "semantisch" Teil ihrer "Schnittstelle" ist).

Normalerweise könnte ich die Datei nach dem Strukturnamen benennen und diesen Namen erneut verwenden, um die Header-Guards zu definieren.

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

struct a ;

Wird genug sein, 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 eine andere, etwas einfachere, aber weniger modulare Methode: Einige Codes, für die nur Ihre Struktur benötigt wird, müssen weiterhin alle Typen enthalten.

In C++ könnte dies zu interessanten Komplikationen führen, aber dies ist nicht thematisch (kein C++ - Tag), daher werde ich nicht näher darauf eingehen.

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

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

sollen wir es dann wie tippen?

  • 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 schmerzhaft sein kann: Sie müssen das struct-Schlüsselwort ü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 struct Schlüsselwort zu schreiben.

struct MyStructTag ; /* Forward declaration */

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

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

Es ist wichtig , dass Sie immer noch einen Namen für die Struktur haben. Schreiben:

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

erstellt nur eine anonyme Struktur mit einem eingegebenen Namen, und Sie können sie nicht weiterleiten. Also halte dich an folgendes Format:

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

Auf diese Weise können Sie MyStruct überall dort verwenden, wo Sie das Hinzufügen des struct-Schlüsselworts vermeiden möchten, und weiterhin MyStructTag verwenden, wenn ein typedef nicht funktioniert (d. H. Forward-Deklaration).

Bearbeiten:

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

Edit 2018-06-01:

Craig Barnes erinnert uns in seinem Kommentar daran, dass Sie keine separaten Namen für den struct "tag" -Namen und dessen "typedef" -Namen benötigen, wie ich es aus Gründen der Klarheit oben getan habe.

In der Tat könnte der obige Code so geschrieben werden:

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

IIRC, genau das macht C++ mit seiner einfacheren Strukturdeklaration im Hintergrund, um die Kompatibilität mit C zu gewährleisten:

// 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, so dass die Verwendung des gleichen Namens das Lesen einfacher macht, wenn Sie nicht C separate "Namespaces" für verwenden Strukturen und andere Symbole .

129
paercebal

Für eine Strukturdefinition, die für mehrere Quelldateien verwendet werden soll, sollten Sie sie unbedingt in eine Headerdatei einfügen. Fügen Sie dann diese Header-Datei in jede Quelldatei ein, die die Struktur benötigt.

Die extern -Deklaration wird nicht für Strukturdefinitionen verwendet, sondern für Variablendeklarationen (dh 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 folgt:

extern struct a myAValue;

Definieren Sie dann in one source file die tatsächliche Variable:

struct a myAValue;

Wenn Sie dies vergessen oder es versehentlich in zwei Quelldateien definiert haben, werden Sie vom Linker darüber informiert.

33
Greg Hewgill

ah:

#ifndef A_H
#define A_H

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

#endif

jetzt müssen Sie nur noch a.h in die Dateien einfügen, in denen Sie diese Struktur verwenden möchten.

5
fmsf