Initialisieren einer Struktur auf 0

116

Wenn ich eine Struktur wie diese habe:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Was wäre der einfachste Weg, um diese Struktur auf 0 zu initialisieren? Würde das Folgende ausreichen?

myStruct _m1 = {0};

oder Muss ich jedes Mitglied explizit auf 0 setzen?

myStruct _m2 = {0,0};
Daan Timmer
quelle

Antworten:

142

Die erste ist am einfachsten ( erfordert weniger Eingabe ) und funktioniert garantiert. Alle Mitglieder werden auf 0[Ref. 1] gesetzt .
Der zweite ist besser lesbar.

Die Auswahl hängt von den Benutzerpräferenzen oder denen ab, die Ihr Codierungsstandard vorschreibt.

[Ref 1] Referenz C99 Standard 6.7.8.21:

Wenn eine Liste in Klammern weniger Initialisierer enthält als Elemente oder Elemente 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 wie Objekte mit statischer Speicherdauer initialisiert werden.

Gut gelesen:
C und C ++: Teilinitialisierung der automatischen Struktur

Alok Speichern
quelle
9
Ich verwende = {};jedoch. Ich bin mir jedoch nicht sicher, ob dies gültig ist.
William Entriken
15
@FullDecent leere Klammern für die Initialisierung sind eine GNU-Erweiterung.
a3f
2
@ alias65536 Die Frage ist mit C nicht C ++ markiert.
A3 vom
3
Ich habe eine Fehlermeldung erhalten: "fehlende Klammern um den Initialisierer [-Werror = fehlende Klammern]", wahrscheinlich aufgrund eines Mitgliedsarrays: /
DrumM
3
@Edenia. Ich bin nicht einverstanden. Ich weiß schon was foo = {0}bedeutet. Wenn ich sehen würde foo = ZERO_FULL, müsste ich nach der Definition von ZERO_FULL suchen.
Andrew Bainbridge
32

Wenn es sich bei den Daten um statische oder globale Variablen handelt, werden sie standardmäßig mit Nullen gefüllt. Deklarieren Sie sie einfach myStruct _m;

Wenn es sich bei den Daten um eine lokale Variable oder eine vom Heap zugewiesene Zone handelt, löschen Sie sie memsetwie folgt :

memset(&m, 0, sizeof(myStruct));

Aktuelle Compiler (zB neuere Versionen von gcc) optimieren dies in der Praxis recht gut. Dies funktioniert nur, wenn alle Nullwerte (einschließlich Nullzeiger und Gleitkomma-Null) als alle Nullbits dargestellt werden, was auf allen mir bekannten Plattformen zutrifft (aber der C- Standard erlaubt Implementierungen, bei denen dies falsch ist; ich kenne keine solche Implementierung). .

Sie könnten vielleicht codieren myStruct m = {};oder myStruct m = {0};(auch wenn das erste Mitglied von myStructkein Skalar ist).

Meiner Meinung nach ist die Verwendung memsetfür lokale Strukturen die beste und vermittelt besser die Tatsache, dass zur Laufzeit etwas getan werden muss (während globale und statische Daten normalerweise als zur Kompilierungszeit initialisiert verstanden werden können, ohne dass zur Laufzeit Kosten anfallen). .

Basile Starynkevitch
quelle
7
Es gibt keine Garantie dafür, dass das Setzen aller Bytes der Struktur 0dem Initialisieren aller Strukturelemente mit entspricht 0. Auf vielen Plattformen wird dies zutreffen, aber nicht universell.
Sander De Dycker
1
Können Sie ein Beispiel nennen, Sander? Echte Neugier. (Offensichtlich nicht universell wahr bedeutet nicht unbedingt, dass es eine leicht zu erklärende Ausnahme gibt, aber wenn es ...)
Steven Fisher
2
Der C- Standard erlaubt, dass der Nullzeiger (oder eine Null-Gleitkommazahl) im Speicher durch etwas anderes als alle Nullbits dargestellt wird. Sehr wenige und seltsame Implementierungen machen das (ich kann keine nennen).
Basile Starynkevitch
-1, Sie finden die Initialisierung, nach der das OP fragt, möglicherweise hässlich, aber genau das ist vom Standard vorgesehen und kann von allen Compilern problemlos optimiert werden. Dann ist das Formular {}kein gültiges C, sondern nur in C ++ verfügbar.
Jens Gustedt
7
@Steven: Ich kann nur an obskure und / oder alte Plattformen denken. Die C-FAQ enthält eine Liste von Plattformen mit einem NULLZeiger, der nicht nur aus 0Bits besteht: c-faq.com/null/machexamp.html . Und dann besteht die Möglichkeit, dass die Plattform nicht IEEE 754 zur Darstellung von Gleitkommawerten verwendet, sondern eine andere Darstellung, die keinen All- 0Bit- 0.0Wert hat - aber ich kenne zugegebenermaßen keine solche Plattform.
Sander De Dycker
19

Siehe §6.7.9 Initialisierung:

21 Wenn eine in Klammern eingeschlossene Liste weniger Initialisierer enthält als Elemente oder Elemente eines Aggregats oder weniger Zeichen in einem Zeichenfolgenliteral zum Initialisieren eines Arrays bekannter Größe als Elemente im Array, der Rest des Aggregats muss implizit wie Objekte mit statischer Speicherdauer initialisiert werden.

Also ja, beide arbeiten. Beachten Sie, dass in C99 auch eine neue Art der Initialisierung verwendet werden kann, die als designierte Initialisierung bezeichnet wird:

myStruct _m1 = {.c2 = 0, .c1 = 1};
dirkgently
quelle
Vor allem ist dies bereits C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (wichtig für bestimmte Signalverarbeitungsziele)
Tobias