Was ist der syntaktisch richtige Weg, um eine C-Struktur zu deklarieren?

Lesezeit: 6 Minuten

Ich habe C-Strukturen gesehen, die zuvor auf verschiedene Arten deklariert wurden. Warum ist das so und was macht jeder anders?

Zum Beispiel:

struct foo {
  short a;
  int b;
  float c;
};

typedef struct {
  short d;
  int e;
  float f;
} bar;

typedef struct _baz {
  short a;
  int b;
  float c;
} baz;

int main (int argc, char const *argv[])
{
  struct foo a;
  bar b;
  baz c;

  return 0;
}

  • Dies beantwortet Ihre Frage für C nicht, aber ich glaube, dass sie alle für C ++ korrekt sind, obwohl die erste bevorzugt wird. Dies mag sich auch zwischen verschiedenen C-Versionen geändert haben, aber ich lasse jemand anderen darüber sprechen, da ich kein Experte für die Geschichte von C/C++ bin.

    – Merlyn Morgan-Graham

    15. Januar 2011 um 8:10 Uhr

  • C++ ist anders: wenn Sie schreiben struct Foo { }; oder class Foo { }; dort bekommt man Foo kostenlos ohne a typedef.

    – Fred Foo

    15. Januar 2011 um 8:18 Uhr

  • Sie alle werden trotzdem funktionieren, auch wenn sie etwas andere Dinge tun (wie Ihren Namensraum mit zusätzlichen Tags verunreinigen).

    – Merlyn Morgan-Graham

    15. Januar 2011 um 8:20 Uhr

  • @Merlyn – Nicht genau. class X lässt dich erklären X x;aber X ist noch im class / struct Tag-Namespace, der es Leuten erlaubt, böse Dinge wie auszuprobieren class singleton { ... } singleton;

    – Chris Lutz

    15. Januar 2011 um 8:30 Uhr


  • Beachten Sie, dass die Verwendung führender Unterstriche in Ihren Struktur-Tag-Namen mit ziemlicher Sicherheit falsch ist. Es kann Dinge kaputt machen und hat keinen Zweck. Tu es nicht.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    15. Januar 2011 um 13:14 Uhr


Benutzeravatar von Chris Lutz
Chris Lutz

Nun, der offensichtliche Unterschied zeigt sich in Ihrem main:

struct foo a;
bar b;
baz c;

Die erste Erklärung ist von einer un-typedefed struct und braucht die struct Stichwort zu verwenden. Der zweite ist von a typedefed anonym structund so verwenden wir die typedef Name. Die dritte kombiniert sowohl die erste als auch die zweite: Ihr Beispiel verwendet baz (was angenehm kurz ist), könnte aber genauso einfach verwendet werden struct _baz zum gleichen Effekt.

Update: Die Antwort von larsmans erwähnt einen häufigeren Fall, in dem Sie mindestens verwenden müssen struct x { } um eine verknüpfte Liste zu erstellen. Der zweite Fall wäre hier nicht möglich (es sei denn, Sie geben den Verstand auf und verwenden a void * stattdessen) weil die struct ist anonym, und die typedef passiert nicht bis zum struct definiert ist, sodass Sie keine Möglichkeit haben, einen (typsicheren) Zeiger auf die zu erstellen struct typ selbst. Die erste Version funktioniert gut für diese Verwendung, aber die dritte wird meiner Erfahrung nach im Allgemeinen bevorzugt. Geben Sie ihm dafür einen Repräsentanten.

Ein subtilerer Unterschied besteht in der Namensraumplatzierung. In C, struct Tags werden in einem separaten Namensraum von anderen Namen platziert, aber typedef Namen sind es nicht. Also legal ist folgendes:

struct test {
  // contents
};

struct test *test() {
  // contents
}

Aber das Folgende ist nicht, weil es mehrdeutig wäre, was der Name ist test ist:

typedef struct {
  // contents
} test;

test *test() {
  // contents
}

typedef macht den Namen kürzer (immer ein Plus), fügt ihn aber in denselben Namensraum wie Ihre Variablen und Funktionen. Normalerweise ist dies kein Problem, aber es ist ein subtiler Unterschied, der über die einfache Kürzung hinausgeht.

  • Wäre die Verwendung desselben Namens für das Tag und die Typedef illegal? Oder keine gute Idee? Oder ist das vollkommen in Ordnung? Zum Beispiel: typedef struct mystruct{ } mystruct;

    – SeanRamey

    23. Januar 2018 um 21:23 Uhr


  • Nein, es ist nicht illegal, da sie in verschiedenen Namespaces sitzen. Lesen Sie stackoverflow.com/a/1675446/6214440 für eine gute Erklärung. Beachten Sie auch, dass Sie in C11 anonyme Strukturen definieren können: typedef struct { ... } Foo

    Benutzer6214440

    11. Oktober 2019 um 7:13 Uhr

Es ist weitgehend eine Frage der persönlichen Präferenz. Ich gebe neuen Typen gerne einen Namen, der mit einem Großbuchstaben beginnt, und lasse das weg structalso schreibe ich meistens typedef struct { ... } Foo. Das heißt, ich kann dann nicht schreiben struct Foo.

Die Ausnahme ist, wenn a struct enthält einen Zeiger auf einen eigenen Typ, z

typedef struct Node {
    // ...
    struct Node *next;
} Node;

In diesem Fall müssen Sie auch deklarieren struct Node Typ, da die typedef ist nicht im Geltungsbereich der struct Definition. Beachten Sie, dass beide Namen identisch sein können (ich bin mir nicht sicher, woher die Unterstrich-Konvention stammt, aber ich denke, dass ältere C-Compiler nicht damit umgehen konnten typedef struct X X;).

  • Doh! Ich habe den offensichtlichen Anwendungsfall “verknüpfte Liste” vergessen. +1

    – Chris Lutz

    15. Januar 2011 um 8:12 Uhr

Alle Ihre Verwendungen sind syntaktisch korrekt. Ich bevorzuge die folgende Verwendung

 /* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
  short a;
  int b;
  foo* next;
};

Beachten Sie, dass dies die Verwendung von einfach ermöglicht typedef bereits in der Deklaration der struct selbst, und das sogar für struct die aufeinander verweisen.

  • +1 für einen Bereich, den ich verpasst habe, und fügen Sie das hinzu, wenn Sie es verwenden typedef struct foo foo; in Ihren Kopfzeilen und geben Sie keine Definition von an struct fooBenutzercode hat einen undurchsichtigen Zeiger (d. h. sie können passieren foo * verweist auf Bibliotheksfunktionen und empfängt sie von Bibliotheksfunktionen, kann aber nicht auf die internen Mitglieder zugreifen.) Dies ist gut für die Datenkapselung und eine gängige Redewendung: der Standard FILE * Typ ist ein solches Beispiel dafür.

    – Chris Lutz

    15. Januar 2011 um 8:42 Uhr

Benutzeravatar von Mike T
Mike T

Die Verwirrung entsteht, weil einige der Deklarationen tatsächlich bis zu drei C-Konstrukte deklarieren. Sie müssen den Unterschied beachten zwischen:

  1. Eine typedef-Deklaration,
  2. Eine Strukturdefinition und
  3. Eine Struct-Deklaration.

Sie sind alle sehr unterschiedliche C-Konstrukte. Sie alle machen unterschiedliche Dinge; Sie können sie jedoch zu einem zusammengesetzten Konstrukt kombinieren, wenn Sie möchten.

Sehen wir uns der Reihe nach jede Deklaration an.


struct foo {
  short a;
  int b;
  float c;
};

Hier verwenden wir die grundlegendste Strukturdefinitionssyntax. Wir definieren einen C-Typ und geben ihm den Namen foo in dem Schild Namensraum. Es kann später verwendet werden, um Variablen dieses Typs mit der folgenden Syntax zu deklarieren:

struct foo myFoo;  // Declare a struct variable of type foo.

Diese nächste Deklaration gibt dem Typ einen anderen Namen (Alias) in der global Namensraum. Lassen Sie uns es anhand der vorherigen grundlegenden Deklaration in seine Komponenten zerlegen.

typedef foo bar;   // Declare bar as a variable type, the alias of foo.

bar myBar;         // No need for the "struct" keyword

Ersetzen Sie jetzt einfach “foo” durch die Definition der Struktur und voila!

typedef struct {
  short d;    
  int e;
  float f;
} bar;

typedef struct _baz {
  short a;
  int b;
  float c;
} baz;

Die obige Syntax entspricht der folgenden Deklarationsfolge.

struct _baz {
  short a;
  int b;
  float c;
}

typedef _baz baz;  // Declare baz as an alias for _baz.

baz myBaz;         // Is the same as: struct _baz myBaz;

1389950cookie-checkWas ist der syntaktisch richtige Weg, um eine C-Struktur zu deklarieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy