Warum gibt der Compiler diese Warnung aus: “Missing Initializer”? Ist die Struktur nicht initialisiert?

Lesezeit: 6 Minuten

Benutzeravatar von Shantia
Shantia

Ich erstelle eine Art Frontend für ein Programm. Um das Programm zu starten, verwende ich den Aufruf CreateProcess()die unter anderem einen Zeiger auf a erhält STARTUPINFO Struktur. Um die Struktur zu initialisieren, die ich früher gemacht habe:

STARTUPINFO startupInfo = {0}; // Or even '\0'.
startupInfo.cb = sizeof(startupInfo);

Wenn Sie das Programm mit GCC kompilieren, aktivieren Sie diese Warnungen -Wall -Wextra Es gibt mir eine Warnung, dass ein Initialisierer fehlt, der auf die erste Zeile zeigt.

warning: missing initializer
warning: (near initialization for 'startupInfo.lpReserved')

Also habe ich am Ende gemacht:

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

Und auf diese Weise gibt der Compiler keine Warnung aus. Die Frage ist, was ist der Unterschied zwischen diesen Arten der Initialisierung einer Struktur? Wird die Struktur mit der ersten Methode nicht initialisiert? Welche würden Sie empfehlen?

  • Die Warnung ist genau das: eine Warnung. Es ist in Ordnung, diese spezielle Warnung bei dieser speziellen Gelegenheit zu ignorieren. Der Compiler gibt die Warnung aus, um Ihnen in folgenden Fällen zu helfen: struct struct_with_four_fields x = {1, 2, 3}; wobei nur 3 von 4 Mitgliedern initialisiert werden.

    – pmg

    8. Oktober 2009 um 17:02 Uhr

  • In meinem vorherigen Kommentar wird das 4. Mitglied auf 0 initialisiert.

    – pmg

    8. Oktober 2009 um 17:03 Uhr

  • Eine Warnung vor fehlenden Initialisierern ist im Allgemeinen nicht unvernünftig; Wenn Sie eine Struktur mit 4 Mitgliedern haben und nur für 3 Initialisierer bereitstellen, ist dies wahrscheinlich ein Fehler. Aber { 0 } ist ein gängiges und gut definiertes Idiom zum Initialisieren aller Mitglieder auf Null (rekursiv für jedes Untermitglied definiert) — weshalb spätere Versionen von gcc geändert wurden, um nicht vor diesem speziellen Fall zu warnen.

    – Keith Thompson

    9. September 2013 um 17:24 Uhr

  • @KeithThompson wovon redest du? Ich verwende gcc 4.8.2, und seit der Frage sind fünf Jahre vergangen. PS da war noch eine Mail, die ich am Ende verlinken wollte, aber zu meiner Verwunderung fehlt sie. Vermutlich speichern Mailserver nicht alle Nachrichten, das ist traurig, die Mail wäre für einen nützlich, der auf das Problem wieder trifft.

    – Hallo Engel

    12. September 2014 um 10:07 Uhr


  • @Hi-Angel: Wenn ich ein kleines Programm mit gcc-4.8.1 unter Solaris kompiliere, erhalte ich “Warnung: fehlender Initialisierer”. Wenn ich dasselbe Programm mit gcc-4.8.2 unter Linux Mint kompiliere, erhalte ich keine Warnung. Übrigens die Linie obj = {0}; in dem Nachricht, die Sie verlinkt haben ist kein gültiges C, und gcc 4.8.2 lehnt es als Syntaxfehler ab. Wenn Sie als C++ kompilieren, denken Sie daran, dass es sich um eine andere Sprache handelt und gcc ein anderes Frontend verwendet; Korrekturen im C-Compiler von gcc können für g++ gelten oder nicht.

    – Keith Thompson

    12. September 2014 um 20:41 Uhr

Benutzeravatar von Michael Burr
Michael Burr

GCC ist einfach übermäßig paranoid – meiner Meinung nach ohne guten Grund, aber es ist sicherlich wahr, dass die GCC-Betreuer viel mehr über die Nuancen von C wissen als ich.

Siehe diesen kleinen Diskussionsfaden zum Problem auf der GCC-Mailingliste:

Die Quintessenz jedoch – Initialisieren der Struktur mit just {0} wird das Ganze tatsächlich mit Null initialisieren.

Das C99 standard sagt folgendes in 6.7.8/21 “Initialisierung – Sematik”:

Wenn es weniger Initialisierer in einer in geschweiften Klammern eingeschlossenen Liste gibt als Elemente oder Mitglieder eines Aggregats oder weniger Zeichen in einem Zeichenfolgenliteral, das zum Initialisieren eines Arrays bekannter Größe verwendet wird, als Elemente im Array vorhanden sind, muss der Rest des Aggregats implizit genauso initialisiert werden wie Objekte mit statischer Speicherdauer.

C90 sagt im Wesentlichen dasselbe in 6.5.7 mit etwas anderem Wortlaut (mit anderen Worten, C99 hat hier nichts Neues hinzugefügt).

Beachten Sie auch, dass dies in C++ so erweitert wurde, dass ein leerer Satz geschweifter Klammern “{}“, würde eine Wertinitialisierung für ein Objekt durchführen, weil es Situationen (wie Vorlagen) gab, in denen Sie nicht einmal wussten, welche Mitglieder oder wie viele Mitglieder ein Typ haben könnte. Es ist also nicht nur eine gute Praxis, sondern manchmal auch notwendig eine Initialisierungsliste, die kürzer ist als die Anzahl der Mitglieder, die ein Objekt möglicherweise hat.

  • musste ich hinzufügen -Wno-missing-field-initializers und -Wno-missing-braces so dass GGC aufhörte, über mein Putten zu jammern = {0}; für meine Strukturen. Weiß jemand, ob durch das Deaktivieren dieser Warnung Warnungen für andere Dinge als übersehen werden? = {0}; für Strukturen?

    – Matt Clarkson

    9. August 2011 um 18:30 Uhr


  • Der Fix ist in vorhanden gcc 4.7.0aber nicht gcc 4.6.3.

    – Spleißgerät

    18. Mai 2012 um 11:13 Uhr

  • @spleißer: Welche “die” Lösung? Auch ich kompiliere mit mingw32-g++.exe (GCC) 4.7.2 und diese Warnung in der obigen Redewendung zu erhalten (sogar im genauen Fall von STARTUPINFO).

    – Jan Hudec

    15. Mai 2013 um 12:28 Uhr

  • @Jan Hudec: Überarbeitung 172857. Leider funktionieren die URLs aus meinen vorherigen Kommentaren nicht mehr. Hier ist der Fehler, der mit dem Fix verbunden ist: gcc.gnu.org/bugzilla/show_bug.cgi?id=36750

    – Spleißgerät

    28. Mai 2013 um 0:20 Uhr

  • Ich bekomme immer noch die Warnung, auch mit gcc 4.9.3, wenn ich die leere geschweifte Klammer verwende {} oder {0} Initialisierer in meinen C++-Klassen :/

    – Kamil Kisiel

    4. Juli 2015 um 6:39 Uhr

Dies kann für GCC in C++-Programmen leicht behoben werden, indem die Struktur als initialisiert wird

STARTUPINFO startupInfo = STARTUPINFO();
  • habe vor ein paar tagen genau das gemacht

  • Ein möglicher Fallstrick bei dieser Antwort ist, dass in C++98 die Felder nicht mit Null initialisiert wurden. Das Zero-Initialisierungsverhalten wurde in C++03 hinzugefügt.

    – MM

    16. April 2017 um 13:56 Uhr

  • @MM Vielen Dank für den Hinweis auf die mögliche Falle, aber ich denke, im Dezember 2018 sollte dies keine gefährliche Situation mehr im Code sein. Übrigens finde ich diese Antwort am besten!

    – Peter VARGA

    5. Dezember 2018 um 18:28 Uhr

  • @AlBundy Leider gibt es noch einige Compiler, die die C++98-Initialisierung verwenden (z. B. C++Builder XE5 32-Bit-Modus, den ich gerade zufällig geöffnet habe).

    – MM

    5. Dezember 2018 um 21:30 Uhr

  • Aus diesem Grund musste ich meiner Datei mehr als 10 Codezeilen hinzufügen. Ich bin wirklich wütend. Es wurde versucht, anonyme Objekte in einem Funktionsaufruf zu übergeben. Wenn ich {} oder {0} verwendet habe, habe ich diese Warnung erhalten (als Fehler behandelt). Wenn ich () verwendet habe, denkt gcc, dass es sich um einen Funktionsaufruf handelt …

    – Bencemeszaros

    16. April 2019 um 8:34 Uhr

Benutzeravatar von ecotax
Ökosteuer

Sie haben mit so viele Warnungen wie möglich angefordert
-Wand und -Wextra.

In diesem Fall erhalten Sie eine Warnung, die Ihnen mitteilt, dass Sie nicht alle Felder angegeben haben, was vollkommen gültig ist, aber möglicherweise unbeabsichtigt war.

Sie können diese Warnung durch Hinzufügen unterdrücken
-Wno-missing-field-initializers.

Benutzeravatar von JanX2
JanX2

Die Webseite So initialisieren Sie Strukturen mit All-Elements-zero-or-null diskutiert das zugrunde liegende Problem sehr detailliert:

Als Problemumgehung besteht meine aktuelle Lösung darin, diese Warnung selektiv zu unterdrücken:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
STARTUPINFO startupInfo = {0};
#pragma clang diagnostic pop

Das funktioniert leider nur in Klirren und scheint in GCC nicht zu funktionieren.

Benutzeravatar von Michael F. Hancock
Michael F. Hancock

In C++ können Sie verwenden boost::initialized_value diese Warnung loszuwerden. Ich habe Warnungen für deaktiviert boost; Ich weiß also nicht, ob dies in Ihrem Fall zu anderen Warnungen führen würde. Auf diese Weise müssen Sie die Warnung nicht deaktivieren.

Beispiel:

T bla = boost::initialized_value;

  • Dies setzt jedoch die Verwendung von voraus Schub(?). Wird dies in einigen Versionen von der Standardbibliothek abgedeckt?

    – Peter Mortensen

    27. Juli um 1:54


  • OK, das OP hat das Gebäude verlassen (“Zuletzt gesehen vor mehr als 2 Jahren”). Vielleicht kann es jemand anderes läuten?

    – Peter Mortensen

    27. Juli um 1:56 Uhr

  • Dies setzt jedoch die Verwendung von voraus Schub(?). Wird dies in einigen Versionen von der Standardbibliothek abgedeckt?

    – Peter Mortensen

    27. Juli um 1:54


  • OK, das OP hat das Gebäude verlassen (“Zuletzt gesehen vor mehr als 2 Jahren”). Vielleicht kann es jemand anderes läuten?

    – Peter Mortensen

    27. Juli um 1:56 Uhr

1418680cookie-checkWarum gibt der Compiler diese Warnung aus: “Missing Initializer”? Ist die Struktur nicht initialisiert?

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

Privacy policy