Struktur initialisieren/auf null/null zurücksetzen
Lesezeit: 5 Minuten
Hari
struct x {
char a[10];
char b[20];
int i;
char *c;
char *d[10];
};
Ich fülle diese Struktur und verwende dann die Werte. Bei der nächsten Iteration möchte ich alle Felder auf zurücksetzen 0 oder null bevor ich anfange, es wiederzuverwenden.
Wie kann ich das machen? Kann ich benutzen memset oder muss ich alle mitglieder durchgehen und dann einzeln machen?
David Heffernan
Definieren Sie eine konstante statische Instanz der Struktur mit den Anfangswerten und weisen Sie dann einfach diesen Wert Ihrer Variablen zu, wann immer Sie sie zurücksetzen möchten.
Zum Beispiel:
static const struct x EmptyStruct;
Hier verlasse ich mich auf die statische Initialisierung, um meine Anfangswerte festzulegen, aber Sie könnten einen Struct-Initialisierer verwenden, wenn Sie andere Anfangswerte wünschen.
Dann kannst du jedes Mal um die Schleife herum schreiben:
myStructVariable = EmptyStruct;
@David Heffernan: Ist das besser als die Verwendung memset wenn ich nur alles zurücksetzen will 0??
– hari
31. Juli 2011 um 19:31 Uhr
@hari Ich würde diesen Ansatz selbst bevorzugen. Verwenden memset macht mich schmutzig. Ich ziehe es vor, den Compiler, wo immer möglich, um das Speicherlayout kümmern zu lassen. Genau genommen eine solche Verwendung von memset ist nicht portierbar, aber in der Praxis wäre ich erstaunt, wenn Sie Ihren Code jemals irgendwo kompiliert haben, was wichtig ist. Sie können memset also wahrscheinlich sicher verwenden, wenn Sie es bevorzugen.
– David Heffernan
31. Juli 2011 um 19:33 Uhr
@hari, es ist konzeptionell besser, da Sie Standardinitialisierungswerte angeben (so etwas wie ein Objektfabrikmuster).
– Diego Sevilla
31. Juli 2011 um 19:34 Uhr
@cnicutar Ich weiß das. Beachten Sie, dass meine Antwort empfiehlt, memset nicht zu verwenden. Beachten Sie auch den Kommentar, in dem ich auf die Nichtportabilität der Verwendung von Memset als Mittel zur Zuweisung von Nullwerten hinweise. Mein vorheriger Kommentar weist nur darauf hin, dass 0-Bits ausnahmslos Gleitkomma-Nullen entsprechen.
– David Heffernan
31. Juli 2011 um 20:19 Uhr
@ kp11 Zitat bitte
– David Heffernan
15. Oktober 2014 um 5:25 Uhr
Der Weg, so etwas zu tun, wenn Sie modernes C (C99) haben, ist die Verwendung von a zusammengesetztes Literal.
a = (const struct x){ 0 };
Dies ist Davids Lösung etwas ähnlich, nur dass Sie sich keine Gedanken darüber machen müssen, ob Sie eine leere Struktur deklarieren oder ob Sie sie deklarieren sollen static. Wenn Sie die verwenden const Wie ich es getan habe, steht es dem Compiler frei, das zusammengesetzte Literal gegebenenfalls statisch im Nur-Lese-Speicher zuzuweisen.
Wie alle Optimierungen ist dies vollständig vom Compiler abhängig, sodass Sie überprüfen müssen, was Ihr Compiler produziert. Bei modernen Compilern “normalerweise” nicht, diese können Initialisierungen sehr gut verfolgen und tun nur das Notwendige, nicht mehr. (Und denken Sie nicht, dass solche Dinge Probleme sind, bevor Sie eine echte Verlangsamung messen. Normalerweise sind sie es nicht.)
– Jens Gustedt
17. Juni 2014 um 11:59 Uhr
“Fehlender Initialisierer”-Warnungen sind wirklich falsch. Die C-Norm schreibt genau vor, was dann passieren muss, und sieht das vor { 0 } als Standardinitialisierer. Schalten Sie diese Warnung aus, es ist ein falscher Fehlalarm.
– Jens Gustedt
5. April 2015 um 16:00 Uhr
Ist das “const” wirklich notwendig? Sicherlich könnte der Compiler es richtig optimieren, da es sich um ein Literal handelt, das nur für diese Zuweisung verwendet wird.
– Sam Watkins
12. November 2015 um 10:09 Uhr
@JensGustedt Wird diese Typumwandlung wirklich benötigt? Kann ich das nicht so schreiben? struct xa = (const){0};
– Patrick
18. Februar 2017 um 14:11 Uhr
@Patrick, obwohl die Syntax ähnlich ist, ist dies keine Umwandlung, sondern ein “zusammengesetztes Literal”. Und Sie verwechseln Initialisierung und Zuweisung.
– Jens Gustedt
18. Februar 2017 um 20:31 Uhr
Besser als alles oben Genannte ist es, die Standard-C-Spezifikation für die Strukturinitialisierung zu verwenden:
struct StructType structVar = {0};
Hier sind alle Bits Null (immer).
Ich glaube nicht, dass Sie das jedes Mal um eine Schleife herum tun können
– David Heffernan
31. Juli 2011 um 19:35 Uhr
Das soll tatsächlich funktionieren. Aber leider beschweren sich gcc & g++ darüber. gcc generiert Warnungen, während g++ einen Fehler generiert. Ich weiß, dass gcc & g++ daran schuld sind (sie sollten der Standard-C-Spezifikation folgen), aber dennoch ist es für eine gute Portabilität zwingend erforderlich, eine solche Einschränkung zu berücksichtigen.
– Cyan
10. März 2015 um 13:00 Uhr
@Cyan Sie können verwenden {} in C++. Die gcc-Entwickler scheinen unsicher, ob C++ unterstützen soll {0} und ich bin mit diesem Teil des Standards selbst nicht vertraut.
– Matthäus Lesen
24. März 2015 um 16:37 Uhr
@Matthew: Ja, eigentlich habe ich memset() verwendet, weil es zu viele Portabilitätsprobleme gab {0} oder {}. Ich bin mir nicht sicher, ob die C- und C++-Standards zu diesem Thema klar und synchron sind, aber Compiler sind es anscheinend nicht.
– Cyan
25. März 2015 um 7:27 Uhr
geht das in so einem fall? struct StructType structVar = malloc (sizeof(StructType)); structVar ={0}
– Sam Thomas
13. Juni 2018 um 19:03 Uhr
In C ist es üblich, den Speicher für a auf Null zu setzen struct verwenden memset:
struct x myStruct;
memset(&myStruct, 0, sizeof(myStruct));
Technisch gesehen glaube ich nicht, dass dies portabel ist, weil es davon ausgeht, dass die NULL Ein Zeiger auf einer Maschine wird durch den ganzzahligen Wert 0 dargestellt, aber er wird häufig verwendet, da dies auf den meisten Maschinen der Fall ist.
Wenn Sie von C zu C++ wechseln, achten Sie darauf, diese Technik nicht für jedes Objekt anzuwenden. C++ macht dies nur für Objekte ohne Mitgliedsfunktionen und ohne Vererbung zulässig.
Rudy Velthuis
Wenn Sie einen C99-kompatiblen Compiler haben, können Sie verwenden
mystruct = (struct x){0};
Andernfalls sollten Sie tun, was David Heffernan geschrieben hat, dh erklären:
struct x empty = {0};
Und in der Schleife:
mystruct = empty;
Sie können verwenden memset mit der Größe der Struktur:
struct x x_instance;
memset (&x_instance, 0, sizeof(x_instance));
Archmed
Ich glaube, Sie können einfach die leere Menge zuweisen ({}) zu Ihrer Variablen.
struct x instance;
for(i = 0; i < n; i++) {
instance = {};
/* Do Calculations */
}
Dies ist kein gültiges C, nicht einmal C99. Es muss ein zusammengesetztes Literal sein, wie in JensGustedts Antwort oben.