Ich habe ein großes Array in C (nicht C ++, wenn das einen Unterschied macht). Ich möchte alle Mitglieder mit demselben Wert initialisieren.
Ich könnte schwören, dass ich einmal einen einfachen Weg kannte, dies zu tun. Ich könnte es memset()
in meinem Fall verwenden, aber gibt es keine Möglichkeit, dies zu tun, die direkt in die C-Syntax integriert ist?
enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };
undstruct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };
. Wenn Sie die Auslassungspunkte entfernen…
, werden diese Fragmente unter C99 oder C11 kompiliert.memset()
Spezifische Diskussion: stackoverflow.com/questions/7202411/… Ich denke, es funktioniert nur für 0.Antworten:
Solange dieser Wert nicht 0 ist (in diesem Fall können Sie einen Teil des Initialisierers weglassen und die entsprechenden Elemente werden auf 0 initialisiert), gibt es keinen einfachen Weg.
Übersehen Sie jedoch nicht die offensichtliche Lösung:
Elemente mit fehlenden Werten werden auf 0 initialisiert:
Dies initialisiert also alle Elemente auf 0:
In C ++ initialisiert eine leere Initialisierungsliste auch jedes Element auf 0. Dies ist mit C nicht zulässig :
Denken Sie daran, dass Objekte mit statischer Speicherdauer auf 0 initialisiert werden, wenn kein Initialisierer angegeben ist:
Und diese "0" bedeutet nicht unbedingt "All-Bits-Null", daher ist die Verwendung der oben genannten Punkte besser und portabler als memset (). (Gleitkommawerte werden auf +0 initialisiert, Zeiger auf Nullwert usw.)
quelle
Wenn Ihr Compiler GCC ist, können Sie die folgende Syntax verwenden:
Lesen Sie die detaillierte Beschreibung: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
quelle
int
statischen Daten 65536 s hinzufügen , was 256 K entspricht - genau die Größe, die Sie beobachtet haben.int
s statisch initialisieren , erhaltenint foo1 = 1, foo2 = 1, ..., foo65536 =1;
Sie die gleiche Vergrößerung.bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
obwohl ich nicht sicher bin, ob das besser lesbar ist als das vollständige Formular.Zum statischen Initialisieren eines großen Arrays mit demselben Wert ohne mehrfaches Kopieren und Einfügen können Sie Makros verwenden:
Wenn Sie den Wert ändern müssen, müssen Sie den Austausch nur an einer Stelle durchführen.
Bearbeiten: mögliche nützliche Erweiterungen
(mit freundlicher Genehmigung von Jonathan Leffler )
Sie können dies leicht verallgemeinern mit:
Eine Variante kann erstellt werden mit:
das funktioniert mit Strukturen oder zusammengesetzten Arrays.
Makronamen sind verhandelbar.
quelle
VAL_1X
es sich nicht um eine einzelne Ganzzahl, sondern um eine Liste handelt. Wie bei Amigable-Status ist dies auch bei eingebetteten Systemen der Fall, bei denen Sie die Init-Werte eines EEPROM- oder Flash-Speichers definieren möchten. In beiden Fällen können Sie nicht verwendenmemset()
.Wenn Sie sicherstellen möchten, dass jedes Mitglied des Arrays explizit initialisiert wird, lassen Sie einfach die Dimension in der Deklaration weg:
Der Compiler leitet die Dimension aus der Initialisierungsliste ab. Leider kann bei mehrdimensionalen Arrays nur die äußerste Dimension weggelassen werden:
ist OK, aber
ist nicht.
quelle
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Ich habe Code gesehen, der diese Syntax verwendet:
Besonders nützlich ist es, wenn Sie ein Array erstellen, das Aufzählungen als Index verwendet:
Dies hält die Dinge in Ordnung, auch wenn Sie einige der Enum-Werte nicht in der richtigen Reihenfolge schreiben.
Mehr über diese Technik finden Sie hier und hier .
quelle
char const *array[] = { ... };
oder sogarchar const * const array[] = { ... };
, oder ?Ich denke das ist besser als
falls sich die Größe des Arrays ändert.
quelle
memset(myArray, VALUE, ARRAY_SIZE);
Sie können den gesamten statischen Initialisierer wie oben beschrieben ausführen, aber es kann eine echte Enttäuschung sein, wenn sich Ihre Arraygröße ändert (wenn sich Ihr Array ändert, wenn Sie nicht die entsprechenden zusätzlichen Initialisierer hinzufügen, erhalten Sie Müll).
memset gibt Ihnen einen Laufzeit-Treffer für die Ausführung der Arbeit, aber kein richtig ausgeführter Code-Größen-Treffer ist immun gegen Änderungen der Array-Größe. Ich würde diese Lösung in fast allen Fällen verwenden, wenn das Array größer als beispielsweise ein paar Dutzend Elemente war.
Wenn es wirklich wichtig wäre, dass das Array statisch deklariert wird, würde ich ein Programm schreiben, um das Programm für mich zu schreiben und es Teil des Erstellungsprozesses zu machen.
quelle
memset
, um das Array zu initialisieren?Hier ist ein anderer Weg:
Sehen:
C-Erweiterungen
Designated inits
Stellen Sie dann die Frage: Wann kann man C-Erweiterungen verwenden?
Das obige Codebeispiel befindet sich in einem eingebetteten System und wird niemals das Licht eines anderen Compilers sehen.
quelle
Zum Initialisieren von 'normalen' Datentypen (wie Int-Arrays) können Sie die Klammer-Notation verwenden, die Werte werden jedoch nach dem letzten auf Null gesetzt, wenn noch Platz im Array vorhanden ist:
quelle
Wenn das Array int oder irgendetwas mit der Größe von int ist oder die Größe Ihres Mem-Musters genau zu einem int passt (dh alle Nullen oder 0xA5A5A5A5), ist es am besten, memset () zu verwenden .
Andernfalls rufen Sie memcpy () in einer Schleife auf, die den Index verschiebt.
quelle
Eine leicht ironische Antwort; Schreiben Sie die Erklärung
in Ihrer bevorzugten Array-fähigen Sprache (meine ist Fortran, aber es gibt viele andere) und verknüpfen Sie sie mit Ihrem C-Code. Sie möchten es wahrscheinlich als externe Funktion zusammenfassen.
quelle
Es gibt eine schnelle Möglichkeit, ein Array eines beliebigen Typs mit einem bestimmten Wert zu initialisieren. Es funktioniert sehr gut mit großen Arrays. Der Algorithmus ist wie folgt:
Für
1 000 000
Elementeint
Array ist es 4 mal schneller als normale Schleifeninitialisierung (I5, 2 Kerne, 2,3 GHz, 4GiB Speicher, 64 Bits):loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
quelle
memfill()
Code ungefähr 1200 µs benötigt. Bei nachfolgenden Iterationen dauert die Schleife jedoch ungefähr 900-1000 µs, während dermemfill()
Code 1000-1300 µs benötigt. Die erste Iteration wird wahrscheinlich durch die Zeit beeinflusst, in der der Cache gefüllt wird. Kehren Sie die Tests um undmemfill()
ist beim ersten Mal langsam.Niemand hat die Indexreihenfolge für den Zugriff auf die Elemente des initialisierten Arrays erwähnt. Mein Beispielcode gibt ein anschauliches Beispiel dafür.
Die Ausgabe ist:
quelle
<iostream>
nicht gültig ist ,C
wiestd::cout
,std::cin
usw. ist der Teilstd::namespace
undC
nicht unterstütztnamespaces
. Versuchen Sie es mit<stdio.h>
fürprintf(...)
statt.Die kurze Antwort lautet: Wenn Sie die Optimierung zur Kompilierungszeit aktivieren, werden Sie nichts Besseres tun:
Zusätzlicher Bonus: Der Code ist tatsächlich lesbar :)
quelle
Beispiel: int array [10]; Memset (Array, -1, 10 * sizeof (int));
quelle
Es gibt die o / p 5 5 5 5 5 5 ...... bis zur Größe des gesamten Arrays
quelle
Ich weiß, dass der Benutzer
Tarski
diese Frage auf ähnliche Weise beantwortet hat, aber ich habe einige weitere Details hinzugefügt. Verzeihen Sie etwas von meinem C, denn ich bin ein bisschen verrostet, da ich eher dazu neige, C ++ zu verwenden, aber hier ist es.Wenn Sie die Größe des Arrays im Voraus kennen ...
Es gibt ein paar Einschränkungen oben; Eine davon ist, dass sie
UINT myArray[size];
bei der Deklaration nicht direkt initialisiert wird. Der nächste Codeblock oder Funktionsaufruf initialisiert jedoch jedes Element des Arrays mit demselben gewünschten Wert. Die andere Einschränkung ist, dass Sieinitializing function
für jeden, dentype
Sie unterstützen , eine schreiben müssen, und Sie müssten auch dieprintArray()
Funktion ändern , um diese Typen zu unterstützen.Sie können diesen Code mit einem Online-Complier ausprobieren, den Sie hier finden .
quelle
Beachten Sie für die verzögerte Initialisierung (dh die Initialisierung des Klassenmitgliedskonstruktors) Folgendes:
quelle
Ich weiß, dass in der ursprünglichen Frage ausdrücklich C und nicht C ++ erwähnt wird, aber wenn Sie (wie ich) hierher gekommen sind, um nach einer Lösung für C ++ - Arrays zu suchen, ist hier ein guter Trick:
Wenn Ihr Compiler Fold-Ausdrücke unterstützt , können Sie Template Magic verwenden und
std::index_sequence
eine Initialisierungsliste mit dem gewünschten Wert erstellen. Und Sie können es sogarconstexpr
und fühlen sich wie ein Chef:Sie können sich den Code bei der Arbeit ansehen (bei Wandbox)
quelle
Ich sehe keine Anforderungen in der Frage, daher muss die Lösung generisch sein: Initialisierung eines nicht spezifizierten möglicherweise mehrdimensionalen Arrays, das aus nicht spezifizierten möglicherweise Strukturelementen mit einem anfänglichen Elementwert aufgebaut ist:
Ergebnis:
EDIT:
start+element_size
geändert zu(char*)start+element_size
quelle
sizeof(void)
es überhaupt gültig ist.memcpy()
mit dem Zielbereich überschneiden. Mit einer naiven Implementierung vonmemcpy()
kann es funktionieren, aber es ist nicht erforderlich, dass das System es funktioniert.Früher (und ich sage nicht, dass es eine gute Idee ist) haben wir das erste Element gesetzt und dann:
memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);
Ich bin mir nicht einmal sicher, ob es nicht mehr funktionieren würde (das würde von der Implementierung von memcpy abhängen), aber es funktioniert, indem das ursprüngliche Element wiederholt in das nächste kopiert wird - funktioniert sogar für Arrays von Strukturen.
quelle
memcpy
im Falle einer Überlappung der Bottom-Up- oder Top-Down-Kopierreihenfolge entsprechen, dies jedoch nicht tun.memmove()
funktioniert es nicht.Wenn Sie parallel meinen, denke ich, dass der Komma-Operator in Verbindung mit einem Ausdruck dies tun kann:
oder wenn Sie in einem einzelnen Konstrukt meinen, können Sie dies in einer for-Schleife tun:
// Beachten Sie, dass der Kommaoperator in einer Argumentliste nicht der oben beschriebene Paralleloperator ist.
Sie können eine Array-Dekleration initialisieren:
Sie können malloc / calloc / sbrk / alloca / etc aufrufen, um einem Objekt einen festen Speicherbereich zuzuweisen:
und Zugriff auf die Mitglieder durch:
Usw.
quelle