Warum werden Typedef-Namen in der Struct-Deklaration in C zweimal verwendet?
Lesezeit: 6 Minuten
Bei der Erforschung von Warteschlangen in C bin ich auf ein Beispiel gestoßen, das dem folgenden ähnelt. Warum wird die Struktur sowohl am Anfang der geschweiften Klammern als auch danach benannt? Warum wird der Strukturtyp innerhalb der Struktur erneut verwendet, wenn ein Element desselben Typs hinzugefügt wird? Sind diese Dinge überflüssig oder gibt es einen Punkt?
Schlagen Sie vor, NIEMALS einen Strukturnamen und einen identischen Typnamen zu verwenden. Verwenden typedef struct QUEUE_ITEM {...} queue_item_t;
– Paul Ogilvie
4. September 2015 um 19:33 Uhr
Ich habe für die Wiedereröffnung gestimmt, weil die doppelte Frage nicht genau dasselbe stellte.
– Jonathon Reinhart
4. September 2015 um 19:33 Uhr
@JonathonReinhart Genau! Ich habe die Antwort eingegeben, als ich eine Menüleistenbenachrichtigung erhalte, die besagt, dass die Frage geschlossen wurde
– Jack
4. September 2015 um 19:34 Uhr
@PaulOgilvie Du solltest deine Typen nicht mit beenden _t weil es von POSIX reserviert ist.
Beachten Sie zunächst, dass diese gesamte Anweisung a definiert typedef.
3) Sagt, dass der neue Typ, den wir gerade definieren (via typedef) ist gehen zu benannt werden queue_item_t.
1) Der Name der Struktur (die im Laufe der Zeit einen neuen Namen erhält) wird benannt struct queue_item_t. Das ist sein vollständiger Name, einschließlich struct vorne.
2) Da der neue Typ noch nicht existiert (denken Sie daran, wir sind noch dabei, ihn zu definieren), müssen wir den einzigen Namen verwenden, den er bisher hat, nämlich struct queue_item_taus 1).
Beachten Sie, dass Sie haben können anonym struct Definitionendie es Ihnen ermöglichen, den Namen wegzulassen 1). Ein einfaches Beispiel:
typedef struct {
int x, y, z;
} vector3;
Da wir in Ihrem Beispiel jedoch die Struktur benötigen, um auf sich selbst verweisen zu können, wird die next Zeiger muss einen bereits definierten Typ haben. Wir können das durch vorwärts deklarieren die Struktur, typdefinieren Sie sie und definieren Sie dann die Struktur mit der typedefd Typ für next:
Unterbricht das Hin- und Herbewegen eines Zeigers von size_t oder uintptr_t das strikte Aliasing?
Hinweis: Ich denke hier alles über struct gilt für union.
– chux – Wiedereinsetzung von Monica
4. September 2015 um 20:12 Uhr
Die disziplinierte Verwendung von Typedefs ist in Ordnung. Linus mag es nicht; Das ist nur wichtig, wenn Sie Linux-Kernel-Code schreiben. Was verrückt ist, ist das Mischen von “typedef struct foo {..} foo_t” mit “typedef struct bar { …} * bar_t” und ähnlicher Code-Verschleierung. Oder Unsinn wie “#define foo_t struct foo”.
– Arie Stephens
4. September 2015 um 20:52 Uhr
Ändern wir die Deklaration ein wenig, um die Diskussion leichter nachvollziehen zu können:
C unterstützt mehrere verschiedene Namensräume; ein Namensraum ist reserviert Tag-Namen zu Unions, Strukturen und Aufzählungstypen. In diesem Fall ist der Tag-Name queue_item. Ein weiterer Namensraum ist für reguläre Bezeichner reserviert, einschließlich Typedef-Namen wie QueueItemType.
Das next member wird verwendet, um auf eine andere Instanz des Typs zu verweisen struct queue_item (dh das nächste Element in der Warteschlange). Es ist als Zeiger auf deklariert struct queue_item aus zwei Gründen:
Ein Strukturtyp darf kein enthalten Beispiel von sich selbst; Zum einen müsste der Typ unendlich groß sein (struct queue_item enthält ein Mitglied nextdie ein struct queue_item die ein Mitglied enthält nextdie ein struct queue_item die ein Mitglied enthält next, Ad infinitum);
Die Strukturtypdefinition ist es nicht Komplett bis zur Schließung }und Sie können kein deklarieren Beispiel von unvollständiger Art. Sie können jedoch a deklarieren Zeiger zu einem unvollständigen Typ, was wir unten tun:
struct queue_item *nächster;
Warum nicht verwenden QueueItemType *next; Anstatt von struct queue_item *next? Auch hier ist die Strukturtypdefinition nicht Komplett am Punkt next wird deklariert; der typedef-Name QueueItemType existiert noch nicht. Allerdings ist der Tag-Name queue_item ist für den Compiler bereits sichtbar, sodass wir Zeiger mithilfe des Typs deklarieren können struct queue_item.
Da Tag-Namen und Typedef-Namen unterschiedliche Namensräume belegen, ist es möglich, denselben Namen ohne Kollision sowohl für den Tag-Namen als auch für den Typedef-Namen zu verwenden. Der Compiler unterscheidet zwischen den beiden durch das Vorhandensein von struct Stichwort.
Zunächst schlage ich vor, NIEMALS einen Strukturnamen und einen identischen Typnamen zu verwenden. Verwenden typedef struct QUEUE_ITEM {...} queue_item_t;
Zu der Frage: Wenn Sie eine “rekursive Datenstruktur” erstellen möchten, dh eine Datenstruktur, die Zeiger auf Instanzen von sich selbst enthält, müssen Sie dem Compiler sagen können: “Dieses Feld ist ein Zeiger auf eine von uns . Du weißt noch nicht ganz, wie wir aussehen, weil ich es noch definiere, also reserviere einfach Platz für einen Zeiger.“ Dazu erklärst du dich
struct T {
...
struct T *ptr;
....
};
Mit dem Finale } queue_item_t; Sie erstellen einen neuen Namen für die Struktur.
Sie schlagen vor, NIEMALS einen Strukturnamen und einen identischen Typnamen zu verwenden, warum?
– Fiddle Bits
4. September 2015 um 19:44 Uhr
Weil es verwirrend ist und wenig weiß, dass sie sich in zwei verschiedenen Namensräumen (Tags und Typedefs) befinden.
– Paul Ogilvie
4. September 2015 um 22:21 Uhr
“struct foo {…} ” ist eine Sache. Es definiert eine Struktur, Sie müssen an jeder Stelle, an der Sie sie verwenden, “struct foo” eingeben.
“typedef … foo” definiert einen neuen Typ, also geben Sie einfach “foo” dort ein, wo Sie es verwenden.
“typedef struct foo {…} foo” ist ein Idiom, also können Sie beide verwenden, höchstwahrscheinlich nur “foo”, um Tastatureingaben und visuelle Verschmutzung zu sparen.
11755200cookie-checkWarum werden Typedef-Namen in der Struct-Deklaration in C zweimal verwendet?yes
Mögliche Antwort: stackoverflow.com/questions/252780/…
– Paolo
4. September 2015 um 19:31 Uhr
Schlagen Sie vor, NIEMALS einen Strukturnamen und einen identischen Typnamen zu verwenden. Verwenden
typedef struct QUEUE_ITEM {...} queue_item_t;
– Paul Ogilvie
4. September 2015 um 19:33 Uhr
Ich habe für die Wiedereröffnung gestimmt, weil die doppelte Frage nicht genau dasselbe stellte.
– Jonathon Reinhart
4. September 2015 um 19:33 Uhr
@JonathonReinhart Genau! Ich habe die Antwort eingegeben, als ich eine Menüleistenbenachrichtigung erhalte, die besagt, dass die Frage geschlossen wurde
– Jack
4. September 2015 um 19:34 Uhr
@PaulOgilvie Du solltest deine Typen nicht mit beenden
_t
weil es von POSIX reserviert ist.– Uigurisches Leben ist wichtig
4. September 2015 um 19:37 Uhr