Ist eine leere Initialisierungsliste gültiger C-Code?
Lesezeit: 5 Minuten
Markus Ahlberg
Es ist üblich zu verwenden {0} a initialisieren struct oder ein array aber betrachten Sie den Fall, wenn das erste Feld kein skalarer Typ ist. Wenn das erste Feld von struct Person ist ein anderer struct oder Array, dann führt diese Zeile zu einem Fehler (error: missing braces around initializer).
struct Person person = {0};
Zumindest erlaubt mir GCC, eine leere Initialisierungsliste zu verwenden, um dasselbe zu erreichen
struct Person person = {};
Aber ist das gültiger C-Code?
Außerdem: Gibt diese Zeile garantiert das gleiche Verhalten, dh eine Null-Initialisierung struct?
struct Person person;
C sollte die Initialisierung von nichts außer garantieren static Variablen, aber ich gehe hier von einem einzigen Satz in Wikipedia aus.
– Millielch
11. Juli 2013 um 9:20 Uhr
Ich möchte hinzufügen, dass ich meinen Code mit pedantischen GCC-Optionen und Warnungen als Fehler erstellt habe. Andere Compiler oder Konfigurationen erlauben möglicherweise die erste Syntax.
– Markus Ahlberg
11. Juli 2013 um 9:21 Uhr
Können Sie sich das ansehen: stackoverflow.com/questions/755305/empty-structure-in-c
– NREZ
11. Juli 2013 um 9:21 Uhr
@millimoose: Variablen, die explizit initialisiert werden, auch mit leeren geschweiften Klammern, sollten besser garantiert werden oder etwas ist schlimm kaputt! Lokale (Auto-)Variablen mit einem Initialisierer sind jedoch eine andere Geschichte.
– ams
11. Juli 2013 um 9:30 Uhr
@ams Ich bezog mich auf die letzte Zeile. Ich hätte sagen sollen “sollte keine implizite Initialisierung garantieren”, um genauer zu sein. Offensichtlich wäre es lächerlich, die explizite Initialisierung zu überspringen
– Millielch
11. Juli 2013 um 11:10 Uhr
zwischenjay
Nein, eine leere Initialisierungsliste ist nicht zulässig. Dies kann auch von GCC beim Kompilieren mit angezeigt werden -std=c99 -pedantic:
a.c:4: warning: ISO C forbids empty initializer braces
Der Grund ist die Art und Weise, wie die Grammatik in §6.7.9 des definiert ist 2011 ISO-C-Standard:
Gemäß dieser Definition muss eine Initialisiererliste mindestens einen Initialisierer enthalten.
Dies ist die richtige Antwort (dass eine leere Initialisierungsliste von der Syntax verboten ist). Es ist ein bisschen unglücklich und es wäre schön, wenn die Standards es zulassen würden, aber sie erlauben im Allgemeinen sowieso keine leeren Objekte, also wird es nicht benötigt. Die Antwort auf den verbleibenden Teil der Frage (Erhalten Sie als-ob-Null, falls vorhanden nein= {...} Teil) ist “ja, wenn das Objekt eine statische Dauer hat, nein, wenn nicht”.
– Torek
11. Juli 2013 um 9:35 Uhr
Dies beantwortet meine Frage. Ich habe immer noch keine narrensichere Möglichkeit, die Struktur in einer einzelnen Zeile zu initialisieren, wenn ich den Typ des ersten Elements nicht kenne (wie es der Fall ist, wenn die Strukturdeklaration automatisch generiert wird), aber das ist so eine andere Frage.
– Markus Ahlberg
11. Juli 2013 um 10:39 Uhr
@MarcusAhlberg: In der Tat ist die Art und Weise, wie der Standard festgelegt wird, in diesem Fall sehr dumm. Der Autor davon muss zu Hause die Logik vergessen haben, um die Angabe von 1 bis N-Initialisierern anstelle von 0 bis N zu ermöglichen, oder, aus der entgegengesetzten Richtung, das Weglassen von 0 bis N-1-Initialisierern anstelle von 0 bis N es.
– Pavel Simerda
5. Juni 2015 um 14:55 Uhr
@torek: Leere Objekte nicht zu unterstützen (weil Sie sie nicht zuweisen und adressieren können) und ein künstliches Limit festzulegen, um nur bis zu N-1-Initialisierer anstelle von N wegzulassen, was dazu führt, dass kein universeller Null-Initialisierer vorhanden ist, sind zwei sehr unterschiedliche Dinge.
– Pavel Simerda
5. Juni 2015 um 14:55 Uhr
@PavelŠimerda: Ich bin verwirrt von Ihrem Kommentar: Ich habe nicht gesagt, dass leere Initialisierer dies nicht sind nützlichnur dass sie es nicht sind zwingend vorhanden sein. Wenn leere Objekte vorhanden sind, benötigen sie entweder einen Sonderfall, der Initialisierer vollständig ausschließt (z. B. “leere Objekte dürfen nicht initialisiert werden”), oder sie benötigen leere Initialisierer. Übrigens funktioniert das Zuweisen und Adressieren leerer Objekte in nicht standardisiertem GNU C gut, es bedeutet nur das &a==&b ist möglich.
– Torek
5. Juni 2015 um 18:49 Uhr
Gemäß dem C99-Standard ist die Array-Erzeugung mit einer leeren Initialisierungsliste verboten. In einer früheren Antwort können Sie sehen, dass die Grammatik diesen Fall nicht beschreibt.
Aber was passiert, wenn Sie ein Array ohne Initialisierung deklarieren? Nun, es hängt vom Compiler ab, den Sie verwenden. Schauen wir uns dieses einfache Beispiel an: int arr[5] = {}.
GCC
Standardmäßig gcc produziert keine Warnungen/Fehler wenn Sie versuchen, diesen Code zu kompilieren. Nicht mal -Wallaber -Wpedantic tut.
warning: ISO C forbids empty initializer braces
Aber wie auch immer gcc Elemente eines Arrays genau so mit Nullen füllen, als ob Sie es explizit angeben würden int arr[5] = {0} siehe Assembly-Ausgabe Gottriegel.
KLANG
Aber standardmäßig werden keine Warnungen zu diesem Fall angezeigt, aber mit Option -Wgnu-empty-initializer tut:
warning: use of GNU empty initializer extension
Clang generiert anderen Assemblercode Gottriegel verhält sich aber genauso.
Der Assembler-Code für Clang sieht ebenfalls identisch aus, vielleicht hat sich das in letzter Zeit geändert.
– Unterkat
26. Februar 2021 um 7:48 Uhr
Lerner
Ja, ab C23 ist eine leere Initialisierung erlaubt. Wenn der Initialisierer der leere Initialisierer ist, ist der Anfangswert derselbe wie die Initialisierung eines statischen Speicherdauerobjekts.
struct Person Person = {}; //Gültig C23
Wenn ein Objekt mit einem leeren Initialisierer initialisiert wird, dann:
— Wenn es einen Zeigertyp hat, wird es mit einem Nullzeiger initialisiert;
— wenn es einen dezimalen Gleitkommatyp hat, wird es auf (positiv oder vorzeichenlos) Null initialisiert und der Quantenexponent ist implementierungsdefiniert166);
— Wenn es einen arithmetischen Typ hat und keinen dezimalen Fließkommatyp, wird es auf (positiv oder vorzeichenlos) Null initialisiert;
— Wenn es sich um ein Aggregat handelt, wird jedes Element (rekursiv) gemäß diesen Regeln initialisiert, und jede Auffüllung wird mit Null-Bits initialisiert.
– Wenn es sich um eine Union handelt, wird das erstgenannte Element (rekursiv) gemäß diesen Regeln initialisiert, und alle Auffüllungen werden mit Null-Bits initialisiert.
Referenz: ISO/IEC 9899:202x (E)
Das ist eine erstaunliche Antwort!
– Dorin Botan
4. Juli um 9:58
14099900cookie-checkIst eine leere Initialisierungsliste gültiger C-Code?yes
C sollte die Initialisierung von nichts außer garantieren
static
Variablen, aber ich gehe hier von einem einzigen Satz in Wikipedia aus.– Millielch
11. Juli 2013 um 9:20 Uhr
Ich möchte hinzufügen, dass ich meinen Code mit pedantischen GCC-Optionen und Warnungen als Fehler erstellt habe. Andere Compiler oder Konfigurationen erlauben möglicherweise die erste Syntax.
– Markus Ahlberg
11. Juli 2013 um 9:21 Uhr
Können Sie sich das ansehen: stackoverflow.com/questions/755305/empty-structure-in-c
– NREZ
11. Juli 2013 um 9:21 Uhr
@millimoose: Variablen, die explizit initialisiert werden, auch mit leeren geschweiften Klammern, sollten besser garantiert werden oder etwas ist schlimm kaputt! Lokale (Auto-)Variablen mit einem Initialisierer sind jedoch eine andere Geschichte.
– ams
11. Juli 2013 um 9:30 Uhr
@ams Ich bezog mich auf die letzte Zeile. Ich hätte sagen sollen “sollte keine implizite Initialisierung garantieren”, um genauer zu sein. Offensichtlich wäre es lächerlich, die explizite Initialisierung zu überspringen
– Millielch
11. Juli 2013 um 11:10 Uhr