Ist eine leere Initialisierungsliste gültiger C-Code?

Lesezeit: 5 Minuten

Benutzeravatar von Marcus Ahlberg
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


Benutzeravatar von interjay
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:

initializer:
         assignment-expression
         { initializer-list }
         { initializer-list , }
initializer-list:
         designation(opt) initializer
         initializer-list , designation(opt) initializer

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


Benutzeravatar des Teilnehmers
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

1409990cookie-checkIst eine leere Initialisierungsliste gültiger C-Code?

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

Privacy policy