Unterschied zwischen 'struct' und 'typedef struct' in C++?

Gibt es in C++ einen Unterschied zwischen:

struct Foo { ... };

und

typedef struct { ... } Foo;
Lösung

In C++ gibt es nur einen feinen Unterschied. Es ist ein Überbleibsel aus C, in dem es einen Unterschied macht.

Der C-Sprachstandard (C89 §3.1.2.3, C99 §6.2.3 und C11 §6.2.3) schreibt getrennte Namensräume für verschiedene Kategorien von Bezeichnern vor, darunter tag identifiers (für struct/union/enum) und ordinary identifiers (für typedef und andere Bezeichner).

Wenn Sie gerade gesagt haben:

struct Foo { ... };
Foo x;

würde man einen Compilerfehler erhalten, da Foo nur im Tag-Namensraum definiert ist.

Sie müssten es deklarieren als:

struct Foo x;

Jedes Mal, wenn Sie sich auf Foo beziehen wollen, müssen Sie es immer als struct Foo bezeichnen. Das wird schnell lästig, also kann man ein typedef hinzufügen:

struct Foo { ... };
typedef struct Foo Foo;

Jetzt verweisen struct Foo (im Tag-Namensraum) und einfach nur Foo (im gewöhnlichen Bezeichner-Namensraum) beide auf dasselbe, und Sie können Objekte vom Typ Foo ohne das Schlüsselwort struct deklarieren.


Das Konstrukt:

typedef struct Foo { ... } Foo;

ist nur eine Abkürzung für die Deklaration und typedef.


Endlich,

typedef struct { ... } Foo;

eine anonyme Struktur deklariert und ein typedef für sie erstellt. Mit diesem Konstrukt hat sie also keinen Namen im Tag-Namensraum, sondern nur einen Namen im Typedef-Namensraum. Das bedeutet, dass es auch nicht weiterdeklariert werden kann. Wenn Sie eine Vorwärtsdeklaration machen wollen, müssen Sie ihm einen Namen im Tag-Namensraum geben.


In C++ verhalten sich alle struct/union/enum/class-Deklarationen so, als wären sie implizit typedef'ed, solange der Name nicht durch eine andere Deklaration mit demselben Namen verdeckt wird. Siehe Michael Burr's Antwort für die vollständigen Details.

Kommentare (16)

Es gibt einen Unterschied, aber einen subtilen. Sehen Sie es so: struct Foo führt einen neuen Typ ein. Die zweite erzeugt einen Alias namens Foo (und nicht einen neuen Typ) für einen unbenannten struct-Typ.

7.1.3 Der typedef-Spezifizierer

1 [...]

Ein mit dem typedef specifier deklarierter Name wird zu einem typedef-name. Innerhalb des Geltungsbereichs seiner Deklaration ist ein typedef-name ist im Rahmen seiner Deklaration syntaktisch äquivalent zu einem Schlüsselwort und benennt den mit dem Bezeichner assoziierten Typ in der in Klausel 8 beschriebenen Weise. Ein typedef-name ist also ein Synonym für einen anderen Typ. Ein typedef-name führt keinen neuen Typ ein, wie es eine Klassendeklaration (9.1) oder eine enum-Deklaration tut.

8 Wenn die typedef-Deklaration eine unbenannte Klasse (oder enum) definiert, wird der erste typedef-Name, der durch die Deklaration deklariert wird, um diesen Klassentyp (oder Enum-Typ) zu bezeichnen, wird der Klassentyp (oder Enum-Typ) nur für Verknüpfungszwecke nur für Verknüpfungszwecke verwendet (3.5). [Beispiel:

typedef struct { } *ps, S; // S is the class name for linkage purposes

Ein typedef wird also immer als Platzhalter/Synonym für einen anderen Typ verwendet.

Kommentare (0)

Es gibt keinen Unterschied in C++, aber ich glaube, in C würde es Ihnen erlauben, Instanzen der Struktur Foo zu deklarieren, ohne dies explizit zu tun:

struct Foo bar;
Kommentare (1)