webentwicklung-frage-antwort-db.com.de

C: typedef struct name {...}; VS typedef struct {...} name;

Wie der Titel sagt, habe ich diesen Code:

typedef struct Book{
    int id;
    char title[256];
    char summary[2048];
    int numberOfAuthors;
    struct Author *authors;
};


typedef struct Author{
    char firstName[56];
    char lastName[56];
};


typedef struct Books{
    struct Book *arr;
    int numberOfBooks;
};

Ich bekomme diese Fehler von gcc:

bookstore.c:8:2: error: unknown type name ‘Author’
bookstore.c:9:1: warning: useless storage class specifier in empty declaration [enabled by default]
bookstore.c:15:1: warning: useless storage class specifier in empty declaration [enabled by default]
bookstore.c:21:2: error: unknown type name ‘Book’
bookstore.c:23:1: warning: useless storage class specifier in empty declaration [enabled by default]

Wenn ich die Typedefs so ändere:

typedef struct{
    char firstName[56];
    char lastName[56];
} Author;

Dann treten keine Warnungen und keine Fehler auf. Nachdem ich http://www.Amazon.com/C-Programming-Language-2nd-Edition/dp/0131103628 und ein paar Stunden googeln gesucht habe, kann ich nicht verstehen, warum die erste Implementierung nicht funktioniert.

32
Alek Sobczyk

Hier gibt es mehrere Dinge. Erstens, wie andere bereits gesagt haben, kann der Compiler eine Beschwerde wegen eines unbekannten Typs einlegen, weil Sie die Typen vor der Verwendung definieren müssen. Wichtiger ist jedoch, die Syntax von 3 Dingen zu verstehen: (1) Strukturdefinition, (2) Strukturdeklaration und (3) Typedef.

Beim Definieren einer Struktur kann die Struktur benannt oder unbenannt sein (wenn sie nicht benannt ist, muss sie sofort verwendet werden (wird erklärt, was dies weiter unten bedeutet)).

struct Name {
   ...
};

Dies definiert einen Typ namens "Strukturname", mit dem eine Strukturvariable deklariert werden kann:

struct Name myNameStruct;

Dies deklariert eine Variable namens myNameStruct, die eine Struktur vom Typ struct Name ist.

Sie können auch eine Struktur definieren und gleichzeitig eine Strukturvariable deklarieren:

struct Name {
   ...
} myNameStruct;

Wie zuvor deklariert dies eine Variable mit dem Namen myNameStruct, die eine Struktur vom Typ struct Name ... ist. Dies geschieht jedoch gleichzeitig mit der Definition des Typsstruct Name.
Der Typ kann erneut verwendet werden, um eine andere Variable zu deklarieren:

struct Name myOtherNameStruct;

Nun ist typedef nur eine Möglichkeit, einen Typ mit einem bestimmten Namen zu aliasieren:

typedef OldTypeName NewTypeName;

In Anbetracht des obigen Typedef ist jedes Mal, wenn Sie NewTypeName verwenden, dasselbe wie mit OldTypeName. In der Programmiersprache C ist dies besonders bei structs hilfreich, da Sie die Möglichkeit haben, bei der Deklaration von Variablen dieses Typs das Wort "struct" wegzulassen und den Namen der struct einfach als eigenen Typ zu behandeln ( wie in C++). Hier ist ein Beispiel, das zuerst die Struktur definiert und dann die Struktur typisiert:

struct Name {
   ...
};

typedef struct Name Name_t;

Im obigen OldTypeName ist struct Name und NewTypeName Name_t. So, jetzt eine Variable vom Typ struct Name zu deklarieren, anstatt zu schreiben:

struct Name myNameStruct;

Ich kann einfach schreiben:

Name_t myNameStruct;

HINWEIS AUCH kann das Typedef mit der Strukturdefinition kombiniert werden, und dies tun Sie in Ihrem Code:

typedef struct {
   ...
} Name_t;

Dies ist auch möglich, wenn Sie die Struktur benennen. Dies ist jedoch überflüssig:

typedef struct Name {
   ...
} Name_t;

NOTE WELL: Da Sie in der obigen Syntax mit "typedef" begonnen haben, ist die gesamte Anweisung eine typedef-Anweisung, in der OldTypeName eine Strukturdefinition ist. Daher interpretiert der Compiler den Namen nach der rechten geschweiften Klammer} als NewTypeName ... es ist NICHT der Variablenname (wie es in der Syntax ohne typedef wäre, in diesem Fall Sie) würde die Struktur definieren und gleichzeitig eine Strukturvariable deklarieren). 

Wenn Sie außerdem typedef angeben, aber an dieser Stelle den Name_t weglassen, haben Sie effektiv eine INCOMPLETE-Typedef-Anweisung erstellt, da der Compiler alles in "struct Name { ... }" als OldTypeName betrachtet und Sie keinen NewTypeName für bereitstellen der typedef Aus diesem Grund ist der Compiler nicht so zufrieden mit dem Code, wie Sie ihn geschrieben haben (obwohl die Nachrichten des Compilers eher kryptisch sind, weil Sie nicht genau wissen, was Sie falsch gemacht haben).

Wenn Sie den Strukturtyp zum Zeitpunkt der Definition nicht benennen, müssen Sie ihn sofort verwenden, um eine Variable zu deklarieren:

struct {
   ...
} myNameStruct;  // declares myNameStruct as a variable with this struct
                 // definition, but the definition cannot be re-used.

Oder Sie können einen unbenannten Strukturtyp in einer Typedef verwenden:

typedef struct {
   ...
} Name_t;

Diese letzte Syntax haben Sie tatsächlich gemacht, als Sie geschrieben haben:

typedef struct{
   char firstName[56];
   char lastName[56];
} Author;

Und der Compiler war glücklich. HTH.

Zu dem Kommentar/der Frage zum Suffix _t:

_t-Suffix ist eine Konvention, die den Lesern des Codes anzeigt, dass der symbolische Name mit _t ein Typname ist (im Gegensatz zu einem Variablennamen). Der Compiler analysiert das _t nicht und weiß es auch nicht. 

Die Standardbibliotheken C89 und insbesondere die C99 definierten viele Typen und wählten das _t für die Namen dieser Typen. Zum Beispiel definiert der Standard C89 wchar_t, off_t, ptrdiff_t. Der C99-Standard definiert viele zusätzliche Typen, wie z. B. uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t usw. Aber _t ist weder reserviert noch speziell geparst, noch wird es vom Compiler beachtet Wenn Sie neue Typen definieren (über Typedef) in C. In C++ verwenden viele Leute die Konvention, um Typnamen mit Großbuchstaben zu beginnen, beispielsweise MyNewType (im Gegensatz zur C-Konvention my_new_type_t). HTH

74
Daniel Goldfarb

Die Syntax von typedef lautet wie folgt:

typedef old_type new_type

Beim ersten Versuch haben Sie den struct Book-Typ und nicht Book definiert. In anderen Worten heißt Ihr Datentyp struct Book und nicht Book.

In der zweiten Form haben Sie die richtige Syntax von typedef verwendet, sodass der Compiler den Typ mit dem Namen Book erkennt.

5
Bechir

Ich denke, wird Ihnen helfen zu verstehen . http://www.tutorialspoint.com/cprogramming/c_typedef.htm

bookstore.c:8:2: error: unknown type name ‘Author’
bookstore.c:21:2: error: unknown type name ‘Book’

Diese werden produziert, weil Sie sie definieren müssen, bevor Sie sie verwenden. Bewegen Sie die Struktur "Autor" und "Bücher" über die Struktur "Buch". Das wird es lösen.

Die Warnung, die Sie erhalten, erklärt auch, warum ein Problem vorliegt. Der Compiler identifiziert "typedef struct Author" als nicht erforderlich, da Sie die Struktur nicht ordnungsgemäß typisieren, sodass der Compiler nichts "lesen" kann.

Da Sie bereits wissen, sollte die Antwort in dieser Form sein

typedef struct {
 ...
 ... 
 ...
} struct-name;

bleib dabei.

0
aiked0

Sie müssen nur Author definieren, bevor Sie Book definieren.

Sie verwenden Author in Book, so dass es zuvor definiert werden muss.

0
EoiFirst