Ich bin kein Anfänger, ich bin mit der folgenden Redewendung sehr vertraut:
typedef struct Foo_ Foo;// I know typedef struct Foo Foo is fine, I'm just trying to make it clearer
struct Foo_
{
int value;
Foo *link;
};
Ich bin nur plötzlich verwirrt, weil ich verstehe, dass es nicht erlaubt ist, einen Namen (Bezeichner) zu verwenden, bevor er deklariert ist. Aber in der Deklaration typedef struct Foo_ Foodie Kennung Foo_ existiert noch nicht! Wie kommt es, dass der Compiler dies zulässt? Würde jemand bitte etwas Licht ins Dunkel bringen, mir erklären, was die Rechtfertigung für diese Art von Syntax ist?
Wikipedia-Zitat: Der Zweck von typedef besteht darin, EXISTIERENDEN Typen alternative Namen zuzuweisen.
— >8 —
Vielen Dank an alle Jungs für so viele hilfreiche Informationen.
Das ist völlig in Ordnung. Der erste Einsatz von struct Tag wie Ihres ist eine Vorwärtsdeklaration des struct Typ.
Beachten Sie jedoch, dass Ihre Verwendung von _Foo ist nicht konform. Bezeichner mit führendem Unterstrich und anschließendem Großbuchstaben sind reserviert. Tu das nicht. Nachgestellter Unterstrich wäre ok.
Bedeutet das typedef struct Foo_ Foo ist eigentlich struct Foo_; typedef struct Foo_ Foo; zusammengeführt?
– Need4Steed
29. November 2012 um 13:08 Uhr
Ich verstehe, es macht Sinn, weil wir so etwas schreiben können typedef struct Foo {...} Foo; wie für typedef struct Foo Foo; nur der {...} Teil entfällt.
– Need4Steed
29. November 2012 um 13:18 Uhr
Ähm, sehr schöner Thread. Ich verstehe es auch. Also, der Compiler sieht wirklich nur das struct wenn a { Anstatt von ; dh, egal wie viele struct foo;` nur wann haben struct foo { ...} das foostruct eingestellt ist. Das folgende Beispiel funktioniert sogar einschließlich -Wall -Wextra: struct foo; struct foo; struct foo { int a, b, c; char *s; };
– Jack
29. November 2012 um 15:06 Uhr
Ekatmur
Dies wird in 6.7.2.3p8 behandelt:
6.7.2.3 Markierungen
Semantik
[…]
8 – Wenn ein Typbezeichner des Formulars struct-or-union Bezeichner tritt anders als als auf [a struct-or-union definition] oder [a struct-or-union declaration]und keine andere Deklaration des Bezeichners als Tag sichtbar ist, dann deklariert es eine unvollständige Struktur oder einen Union-Typ und deklariert den Bezeichner als Tag dieses Typs.
Der Typbezeichner struct Foo in typedef struct Foo Foo ist nicht in einer Definition (struct Foo {...};) oder eine Erklärung (struct Foo;) fällt also unter 6.7.2.3p8.
Beachten Sie, dass a nichts Besonderes ist typedef; man könnte zB auch schreiben
struct A { struct Foo *p; };
und eine vorherige Definition oder Deklaration muss nicht sichtbar sein.
In einer Funktionsdeklaration oder -definition gilt jedoch:
void foo(struct Foo *p);
wenn struct Foo vorher wird dann das nicht deklariert Umfang der Deklaration wird nur die Funktionsdeklaration oder -definition sein und ist nicht typkompatibel mit einer nachfolgenden Deklaration oder Definition von Foo.
Omkant
ISO c99 : 6.2.1 Scopes of identifiers
7
Struktur-, Vereinigungs- und Aufzählungs-Tags haben einen Geltungsbereich, der unmittelbar nach dem Erscheinen des Tags in einem Typbezeichner beginnt, der das Tag deklariert.
typedef struct _Foo Foo; // You can do this because it's just the typedef the new type
struct _Foo *myfoo ; // It's pointer to struct _Foo (an incomplete type)
//but make sure before using myfoo->value
// struct definition should be available
struct _Foo MyFoo; // It's definition of MyFoo but don't forget
// to give the definition of struct _Foo (gcc extension).
struct _Foo; // forward declaration
struct _Foo // It's the definition
{
int value;
Foo *link;
};
Einfach so functions wir tun forward declaration oder typedef vor der eigentlichen Definition der Funktion , also können wir es mit tun struct Auch.
typedef wird verwendet, um eine zu erstellen alias für einen Typ. Aber dieser Typ existiert nicht unbedingt, wenn er typdefiniert ist.
Zum Beispiel,
wenn du es einfach machst:
struct Foo;
und du definierst das nie struct Foo irgendwo im Programm, dann wird es trotzdem kompiliert. Der Compiler würde davon ausgehen, dass es irgendwo definiert ist, und fortfahren. Nur wenn Sie es verwenden, ohne die Struktur zu definieren, tritt ein Fehler auf.
Ähnlich verhält es sich mit typedef auch.
Unter bestimmten Umständen ist es zulässig, a zu verwenden struct ... Typ, bevor es deklariert wird. Es handelt sich dann um einen sogenannten „unvollständigen Typ“.
Beispielsweise ist es zulässig, eine Variable als Zeiger auf eine “unvollständige” Struktur zu deklarieren, sowie (wie Sie sehen können) a typedef.
Mike
Es heißt Forward Declaring. Die Forward-Deklaration ermöglicht es Ihnen, den Namen im Kontext zu verwenden, in dem ein unvollständiger Typ zulässig ist.
Der Compiler “sieht” das typedef-Tag und speichert es, bis der Typ gefunden ist, also solange Sie den Typ dort nach dem typedef deklariert haben, aber vor jeder Verwendung, ist es in Ordnung.
Akp
Mit einer typedef-Deklaration können Sie Ihre eigenen Bezeichner definieren, die anstelle von Typbezeichnern wie int, float und double verwendet werden können. Eine typedef-Deklaration reserviert keinen Speicherplatz.
@Kiril Kirov, wie Sie in Ihrer Frage erklärt haben, ist mein Verständnis, dass es nicht erlaubt ist, einen Namen (Bezeichner) zu verwenden, bevor er deklariert wird. Aber in der Deklaration typedef struct _Foo Foo existiert der Bezeichner _Foo noch nicht! aber typedef prüft nicht auf seine Existenz … das ist Yim, der die Antwort schreibt … versuchen Sie es erneut zu lesen und analysieren Sie sie dann.
– akp
29. November 2012 um 13:00 Uhr
Ich bin nicht derjenige, der die Frage gepostet hat, ich weiß, dass dies zulässig ist (es gibt sogar ein solches Beispiel in der ISO-Norm), ich glaube nur nicht, dass Ihre Antwort für die Frage relevant ist.
– Kiril Kirow
29. November 2012 um 13:10 Uhr
13851200cookie-checktypedef eine Struktur, bevor sie deklariert wirdyes