C-Struktur-Initialisierung mit Labels. Es funktioniert, aber wie?
Lesezeit: 4 Minuten
Andreas Cottrell
Ich habe gestern einen Struct-Initialisierungscode gefunden, der mich für eine Schleife geworfen hat. Hier ist ein Beispiel:
typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
TEST_STRUCT test = {
second: 2,
first: 1
};
printf("test.first=%d test.second=%d\n", test.first, test.second);
}
Überraschenderweise (für mich) ist hier die Ausgabe:
-> testFunc
test.first=1 test.second=2
Wie Sie sehen können, wird die Struktur ordnungsgemäß initialisiert. Mir war nicht bewusst, dass beschriftete Aussagen so verwendet werden können. Ich habe mehrere andere Möglichkeiten zur Strukturinitialisierung gesehen, aber ich habe in keinem der Online-C-FAQs Beispiele für diese Art der Strukturinitialisierung gefunden. Weiß jemand wie/warum das funktioniert?
Sigisaft
Hier ist der Abschnitt des gcc-Handbuchs, der die Syntax der designierten Initialisierer für Strukturen und Arrays erklärt:
Geben Sie in einem Strukturinitialisierer den Namen eines zu initialisierenden Felds mit ‘.Feldname =‘ vor dem Elementwert. Zum Beispiel bei folgender Struktur:
struct point { int x, y; };
folgende Initialisierung
struct point p = { .y = yvalue, .x = xvalue };
ist äquivalent zu
struct point p = { xvalue, yvalue };
Eine andere Syntax, die die gleiche Bedeutung hat und seit GCC 2.5 veraltet ist, ist ‘Feldname:‘, wie hier gezeigt:
Ihr Compiler sollte eine ähnliche Dokumentation haben.
Ausgezeichnet, diese Dokumentation erklärt die Syntax klar: Eine andere Syntax, die die gleiche Bedeutung hat und seit GCC 2.5 veraltet ist, ist `fieldname:’, wie hier gezeigt: struct point p = { y: yvalue, x: xvalue };
– Andrew Cottrell
21. Oktober 2009 um 15:31 Uhr
@AndrewCottrell, diese Syntax “fieldname:” sieht für mich so natürlich (und vorzuziehen) aus, haben Sie eine Idee, warum sie als veraltet angesehen werden sollte?
– Rick
12. Juni 2017 um 4:25 Uhr
@rick die Syntax “fieldname:” ist eine gcc-Erweiterung und war noch nie Teil eines ISO-C-Standards.
– Sigissaft
12. Juni 2017 um 5:51 Uhr
ndim
Dies sind weder Etiketten noch Bitfelder.
Dies ist eine Syntax zum Initialisieren von Strukturmitgliedern aus der Zeit vor C99. Es ist nicht standardisiert, aber zB in gcc verfügbar.
typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
In C99 wurde zum ersten Mal in einem Standard eine Syntax zum Initialisieren bestimmter Strukturmitglieder eingeführt, aber sie sieht etwas anders aus:
typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
Ja, ich war mir des vorgesehenen Initialisierungsformats bewusst. Leider ist dieses Format nicht mit C++ kompatibel! (Nicht in meinen Tests sowieso.) Danke für die Antwort. Gut zu wissen, dass dies nicht standardisiert ist.
– Andrew Cottrell
21. Oktober 2009 um 15:08 Uhr
@Andrew du hast in deiner Frage nie etwas über C++ gesagt
– Pferdemensch
17. Dezember 2009 um 11:23 Uhr
Ja, wie oben erwähnt, sind dies designierte Initialisierer, die Standard-C sind, obwohl Sie auf die Verwendung von Punkten anstelle von Doppelpunkten umsteigen sollten. Und wie Sie bemerken, stecken die meisten Bücher da draußen immer noch irgendwo um 1984 herum in ihrer Syntax fest und erwähnen sie nicht. Weitere lustige Fakten:
–Wenn bestimmte Initialisierer verwendet werden, wird alles, was nicht angegeben ist, mit Null initialisiert. Dies hilft bei außergewöhnlich großen Strukturen, z.
Dies sind wirklich großartige Funktionen, die von jedem C-Compiler unterstützt werden, den ich mir vorstellen kann, da es sich um den Standard handelt. Schade, dass sie nicht so bekannt sind.
Die alternative Syntax (mit Doppelpunkten) sieht für mich so natürlich und vorzuziehen aus. Können Sie erklären, warum wir auf die Verwendung von Punkten anstelle von Doppelpunkten umsteigen sollten?
– Rick
12. Juni 2017 um 4:28 Uhr
Thomas Padron-McCarthy
Es handelt sich nicht wirklich um “beschriftete Anweisungen”, sondern um eine Möglichkeit, den benannten Feldern in der Struktur Anfangswerte zu geben.
Gcc warnt vor “veralteter Verwendung des designierten Initialisierers mit ‘:'”, und in C99 sollten Sie stattdessen schreiben:
TEST_STRUCT test = {
.second = 2,
.first = 1
};
pmg
Diese Syntax ist nicht durch den C-Standard definiert. Abschnitt 6.7.8 Initialization sagt
Wenn Ihr Compiler eine Bezeichnung mit einem Doppelpunkt ohne Diagnosemeldung akzeptiert, bedeutet dies, dass Ihr Compiler nicht standardkonform ist (oder nicht so konfiguriert ist).
14074100cookie-checkC-Struktur-Initialisierung mit Labels. Es funktioniert, aber wie?yes