Ich habe eine kurze Frage zu C-Stil-Strukturen. Ich habe einen Beispielcode durchforstet und eine Struktur gefunden, die folgendermaßen deklariert ist:
%Vor%Bitte beachten Sie, dass STRUCTNAME beim zweiten Mal nicht mehr unterstrichen wird. Mein Verständnis war, dass dies einen einzelnen _STRUCTNAME namens STRUCTNAME deklarieren würde und keine weiteren Objekte dieser Struktur instanziiert werden könnten.
Dies scheint jedoch nicht der Fall zu sein. Eine Struktur dieses Typs wurde nie wirklich in dem Code instanziiert, außer an einer Stelle: in einem globalen Array solcher Objekte, das an zufälligen Orten verwendet wurde:
%Vor%Beachten Sie das Fehlen eines Unterstrichs wieder (was ich dachte, war der Name des instanziierten Objekts?)
Ist mein Verständnis vollständig ausgeschaltet?
Könnte jemand erklären?
Dieser Codeabschnitt macht zwei Dinge:
struct _STRUCTNAME
und typedef
dieser Struktur namens STRUCTNAME
. Der Grund dafür ist, dass im normalen C-Code die Art, wie Sie andernfalls struct
(wie oben) deklarieren würden, wie folgt wäre:
Wenn jedoch typedef
vorhanden ist, können Sie einfach Folgendes verwenden:
Dasselbe gilt für enum
-Deklarationen.
STRUCTNAME
ist der Typdef name.
_STRUCTNAME
ist das 'Tag' für die Struktur, die sich in einem anderen Namensraum befindet.
Vor der ANSI-Standardisierung war der Struktur-Tag-Namespace in vielen Compilern nicht getrennt. Um eine Namenskollision mit dem Typedef-Namen zu verhindern, musste er anders sein. Seit der Standardisierung muss der Tag-Name jedoch nicht anders sein.
Sie sehen dieses Idiom häufig in Windows-Code, ohne Zweifel, weil es in vielen Beispielen aus dem SDK so war. Raymond Chen hat vor einiger Zeit einen Blogeintrag darüber geschrieben:
Ich bin mir auch sicher, dass es einige Kommentare darüber geben wird, wie der _STRUCTNAME
-Bezeichner für die Implementierung reserviert ist. Es ist also keine gute Idee, dieses Formular in jedem Fall zu verwenden.
Ich bin mir auch sicher, dass es einige Kommentare darüber geben wird, wie der
_STRUCTNAME
-Bezeichner für die Implementierung reserviert ist. Es ist also keine gute Idee, dieses Formular in jedem Fall zu verwenden.
OK, ich bin Spiel (aber ich wollte etwas Formatierung, so erhalten Sie stattdessen eine Antwort):
Ein Sprachstandard ist ein Vertrag zwischen Compiler-Writer und Compiler-User, wo jeder verspricht, bestimmte Dinge zu tun.
Die meisten mit _
beginnenden Bezeichner sind für die Implementierung reserviert - einschließlich alle Bezeichner beginnend mit _
, gefolgt von einem Großbuchstaben. Dies bedeutet, dass der Compiler-Writer sie für jeden Zweck verwenden darf, da der Compiler-Benutzer versprochen hat, sie nicht zu verwenden.
Compiler-Benutzer, die ihr Versprechen brechen, bekommen seltsame Ergebnisse.
Umgekehrt ist garantiert, dass alle Bezeichner, die der [anwendbare] Standard für die Implementierung nicht reserviert, dem Compiler-Benutzer zur Verfügung stehen, weil der Compiler-Schreiber versprochen hat, sie nicht zu benutzen.
Compiler-Writer, die ihr Versprechen brechen, erhalten Rückerstattungsanforderungen, wenn der gültige Code seltsame Ergebnisse erzielt.
Meine Präferenz besteht darin, eine nachgestellte _
auf Tag-Namen zu setzen, Wächter usw. einzuschließen, um sicherzustellen, dass ich mich außerhalb des Bereichs der Implementierung befinde; Also:
(Einige Puristen runzeln über typedef
s nur als syntaktischen Zucker, aber C braucht hier und da etwas Zucker, sonst kann es ziemlich langweilig wirken.)
Ich glaube, Ihre Verwirrung ist warum die ID-Liste am Ende der struct
-Definition Instanzen nicht instanziiert. Der Grund dafür ist, dass Sie das Schlüsselwort typedef
eingefügt haben.
Betrachte die syantax für typedef
:
Was Sie getan haben, ist Ihre struct
als Typdefinition. Anstatt Instanzen zu erstellen, definieren Sie einen Typ. Stellen Sie dies dem Instanziieren von Instanzen zur Verfügung, in denen die Struktur den Typ inline definiert:
Wenn Sie das Schlüsselwort typedef
nicht angeben, gibt der Bezeichner nur Instanzen wie üblich an.