1045 Stimmen

typedef struct vs. struct-Definitionen

Ich bin ein Anfänger in der C-Programmierung, aber ich habe mich gefragt, was der Unterschied zwischen der Verwendung von typedef bei der Definition einer Struktur gegenüber der Nichtverwendung von typedef . Meines Erachtens gibt es da keinen Unterschied, sie erreichen das gleiche Ziel.

struct myStruct{
    int one;
    int two;
};

vs.

typedef struct{
    int one;
    int two;
}myStruct;

1 Stimmen

Ich habe gerade hier auf SO gelesen, dass die zweite Option einen Compiler-Fehler verursachen würde?! "Übergabe eines Arguments mit inkompatiblem Zeigertyp" stackoverflow.com/questions/12708897/

8 Stimmen

Eine bessere Antwort (meiner Meinung nach) finden Sie unter aquí .

1339voto

Die gängige Redewendung ist, beides zu verwenden:

typedef struct S { 
    int x; 
} S;

Es handelt sich um unterschiedliche Definitionen. Um die Diskussion klarer zu machen, werde ich den Satz aufteilen:

struct S { 
    int x; 
};

typedef struct S S;

In der ersten Zeile definieren Sie den Bezeichner S innerhalb des struct-Namensraums (nicht im Sinne von C++). Sie können ihn verwenden und Variablen oder Funktionsargumente des neu definierten Typs definieren, indem Sie den Typ des Arguments als struct S :

void f( struct S argument ); // struct is required here

Die zweite Zeile fügt einen Typ-Alias hinzu S in den globalen Namensraum ein und erlaubt Ihnen somit, einfach zu schreiben:

void f( S argument ); // struct keyword no longer needed

Da beide Bezeichner-Namensräume unterschiedlich sind, muss die Definition von S sowohl in den structs als auch in den global spaces ist kein Fehler, da es sich nicht um eine Neudefinition desselben Bezeichners handelt, sondern um die Erstellung eines anderen Bezeichners an einer anderen Stelle.

Um den Unterschied zu verdeutlichen:

typedef struct S { 
    int x; 
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

Sie können eine Funktion mit dem gleichen Namen wie die Struktur definieren, da die Bezeichner in unterschiedlichen Bereichen gehalten werden, aber Sie können keine Funktion mit dem gleichen Namen wie eine typedef wenn diese Identifikatoren kollidieren.

In C++ ist es etwas anders, da sich die Regeln für das Auffinden eines Symbols geringfügig geändert haben. In C++ gibt es immer noch zwei verschiedene Bezeichnerbereiche, aber anders als in C müssen Sie das Schlüsselwort struct/class nicht angeben, wenn Sie das Symbol nur innerhalb des Klassenbezeichnerbereichs definieren:

 // C++
struct S { 
    int x; 
}; // S defined as a class

void f( S a ); // correct: struct is optional

Was sich ändert, sind die Suchregeln, nicht der Ort, an dem die Bezeichner definiert sind. Der Compiler sucht in der globalen Bezeichnertabelle und nach S nicht gefunden wurde, sucht es nach S innerhalb der Klassenbezeichnungen.

Der zuvor vorgestellte Code verhält sich auf dieselbe Weise:

typedef struct S { 
    int x; 
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

Nach der Definition der S Funktion in der zweiten Zeile, die Struktur S kann vom Compiler nicht automatisch aufgelöst werden, und um ein Objekt zu erstellen oder ein Argument dieses Typs zu definieren, müssen Sie auf die Einbeziehung der struct Stichwort:

// previous code here...
int main() {
    S(); 
    struct S s;
}

223voto

Keith Thompson Punkte 240701

struct y typedef sind zwei sehr unterschiedliche Dinge.

El struct Schlüsselwort wird verwendet, um einen Strukturtyp zu definieren oder darauf zu verweisen. Zum Beispiel dies:

struct foo {
    int n;
};

erstellt einen neuen Typ namens struct foo . Der Name foo ist eine Tag ; es ist nur sinnvoll, wenn es unmittelbar vor dem struct Schlüsselwort, da Tags und andere Identifikatoren in verschiedenen Namensräume . (Dies ist ähnlich, aber viel eingeschränkter als das C++-Konzept von namespace s.)

A typedef definiert trotz des Namens keinen neuen Typ, sondern erzeugt lediglich einen neuen Namen für einen bestehenden Typ. Zum Beispiel, gegeben:

typedef int my_int;

my_int ist ein neuer Name für int ; my_int y int sind genau der gleichen Art. Ähnlich verhält es sich mit dem struct Definition oben, können Sie schreiben:

typedef struct foo foo;

Der Typ hat bereits einen Namen, struct foo . Die typedef Deklaration gibt demselben Typ einen neuen Namen, foo .

Die Syntax erlaubt es Ihnen, eine struct y typedef in einer einzigen Erklärung zusammengefasst:

typedef struct bar {
    int n;
} bar;

Dies ist eine gängige Redewendung. Jetzt können Sie diesen Strukturtyp entweder als struct bar oder einfach als bar .

Beachten Sie, dass der Typedef-Name erst am Ende der Deklaration sichtbar wird. Wenn die Struktur einen Zeiger auf sich selbst enthält, müssen Sie die struct Version, um darauf zu verweisen:

typedef struct node {
    int data;
    struct node *next; /* can't use just "node *next" here */
} node;

Einige Programmierer verwenden unterschiedliche Bezeichner für das struct-Tag und für den typedef-Namen. Meiner Meinung nach gibt es dafür keinen guten Grund; die Verwendung desselben Namens ist völlig legal und macht deutlicher, dass es sich um denselben Typ handelt. Wenn Sie unterschiedliche Bezeichner verwenden müssen, sollten Sie zumindest eine einheitliche Konvention verwenden:

typedef struct node_s {
    /* ... */
} node;

(Ich persönlich ziehe es vor, die typedef und bezeichnen den Typ als struct bar . Die typedef spart ein wenig Tipparbeit, aber es verbirgt die Tatsache, dass es ein Strukturtyp ist. Wenn Sie möchten, dass der Typ undurchsichtig ist, kann dies eine gute Sache sein. Wenn sich der Client-Code auf das Mitglied n dann ist es nicht undurchsichtig; es ist eine sichtbare Struktur, und meiner Meinung nach ist es sinnvoll, sie als Struktur zu bezeichnen. Aber viele kluge Programmierer sind in diesem Punkt anderer Meinung als ich. Seien Sie darauf vorbereitet, Code zu lesen und zu verstehen, der so oder so geschrieben wurde).

(C++ hat andere Regeln. Angesichts einer Deklaration von struct blah können Sie den Typ einfach als blah auch ohne Typendefinition. Die Verwendung eines Typedefs könnte Ihren C-Code ein wenig C++-ähnlicher machen - wenn Sie das für gut halten).

97voto

R Samuel Klatchko Punkte 72641

Ein weiterer Unterschied, auf den nicht hingewiesen wurde, besteht darin, dass die Vergabe eines Namens für die Struktur (z. B. struct myStruct) auch die Möglichkeit bietet, Vorwärtsdeklarationen für die Struktur bereitzustellen. In einer anderen Datei könnten Sie also schreiben:

struct myStruct;
void doit(struct myStruct *ptr);

ohne Zugang zur Definition haben zu müssen. Ich empfehle Ihnen, Ihre beiden Beispiele zu kombinieren:

typedef struct myStruct{
    int one;
    int two;
} myStruct;

Dies bietet Ihnen den Komfort des prägnanteren typedef-Namens, erlaubt Ihnen aber immer noch, den vollen struct-Namen zu verwenden, wenn Sie ihn benötigen.

73voto

mmx Punkte 400975

In C (nicht C++) müssen Sie struct-Variablen wie deklarieren:

struct myStruct myVariable;

Um die Möglichkeit zu haben myStruct myVariable; stattdessen können Sie typedef die Struktur:

typedef struct myStruct someStruct;
someStruct myVariable;

Sie können kombinieren struct Definition und typedef s in einer einzigen Anweisung, die einen anonymen Namen deklariert struct y typedef ist es.

typedef struct { ... } myStruct;

49voto

RED SOFT ADAIR Punkte 11611

Wenn Sie struct なくしては typedef werden Sie immer schreiben müssen

struct mystruct myvar;

Es ist illegal, zu schreiben

mystruct myvar;

Wenn Sie die typedef brauchen Sie nicht die struct Präfix nicht mehr.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X