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 wusste, dies zu tun. Ich könnte memset()
in meinem Fall verwenden, aber gibt es keine Möglichkeit, dies in die C-Syntax zu integrieren?
Wenn 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 die offensichtliche Lösung jedoch nicht:
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
Elemente mit fehlenden Werten werden auf 0 initialisiert:
int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...
Dadurch werden alle Elemente auf 0 initialisiert:
int myArray[10] = { 0 }; // all elements 0
In C++ initialisiert eine leere Initialisierungsliste auch jedes Element auf 0. ..__ Dies ist nicht zulässig mit C:
int myArray[10] = {}; // all elements 0 in C++
Denken Sie daran, dass Objekte mit statischer Speicherdauer auf 0 initialisiert werden, wenn kein -Initialisierer angegeben ist:
static int myArray[10]; // all elements 0
Und dass "0" nicht notwendigerweise "All-Bits-Null" bedeutet, so ist die Verwendung des oben genannten Besser und tragbarer als memset (). (Fließkommazahlen werden auf 0 initialisiert .__, Zeiger auf Nullwert usw.)
Wenn Ihr Compiler GCC ist, können Sie folgende Syntax verwenden:
int array[1024] = {[0 ... 1023] = 5};
Schauen Sie sich die ausführliche Beschreibung an: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
Zum statischen Initialisieren eines großen Arrays mit demselben Wert ohne mehrfaches Kopieren und Einfügen können Sie Makros verwenden:
#define VAL_1X 42
#define VAL_2X VAL_1X, VAL_1X
#define VAL_4X VAL_2X, VAL_2X
#define VAL_8X VAL_4X, VAL_4X
#define VAL_16X VAL_8X, VAL_8X
#define VAL_32X VAL_16X, VAL_16X
#define VAL_64X VAL_32X, VAL_32X
int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };
Wenn Sie den Wert ändern müssen, müssen Sie den Austausch nur an einer Stelle vornehmen.
(Mit freundlicher Genehmigung von Jonathan Leffler )
Sie können dies leicht verallgemeinern mit:
#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */
Eine Variante kann erstellt werden mit:
#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */
das funktioniert mit Strukturen oder zusammengesetzten Arrays.
#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)
struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };
makronamen sind verhandelbar.
Wenn Sie sicherstellen möchten, dass jedes Element des Arrays explizit initialisiert wird, lassen Sie die Dimension in der Deklaration einfach weg.
int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Der Compiler leitet die Dimension aus der Initialisierungsliste ab. Leider kann für mehrdimensionale Arrays nur die äußerste Dimension weggelassen werden:
int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
ist in Ordnung, aber
int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
ist nicht.
Ich habe Code mit dieser Syntax gesehen:
char* array[] =
{
[0] = "Hello",
[1] = "World"
};
Besonders nützlich wird es, wenn Sie ein Array erstellen, das Aufzählungen als Index verwendet:
enum
{
ERR_OK,
ERR_FAIL,
ERR_MEMORY
};
#define _ITEM(x) [x] = #x
char* array[] =
{
_ITEM(ERR_OK),
_ITEM(ERR_FAIL),
_ITEM(ERR_MEMORY)
};
Dies hält die Dinge in der richtigen Reihenfolge, auch wenn Sie einige der Aufzählungswerte falsch schreiben.
int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
myArray[i] = VALUE;
}
Ich denke das ist besser als
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...
die Größe des Arrays ändert sich.
Sie können die gesamte statische Initialisierungssache wie oben beschrieben ausführen, aber es kann ein ekliger sein, wenn sich Ihre Array-Größe ändert (wenn Ihr Array eingebettet wird, wenn Sie nicht die entsprechenden zusätzlichen Initialisierer hinzufügen, erhalten Sie Müll.).
memset bietet Ihnen einen Runtime-Treffer für die Arbeit, aber kein korrekter Code-Size-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 einige Dutzend Elemente wäre.
Wenn es wirklich wichtig war, dass das Array statisch deklariert wurde, würde ich ein Programm schreiben, um das Programm für mich zu schreiben und Teil des Erstellungsprozesses zu machen.
Hier ist ein anderer Weg:
static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
//this code intentionally left blank
}
static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
[0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};
Sehen:
Inits bezeichnet
Dann stellen Sie 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.
Eine leicht witzige Antwort; schreibe die Aussage
array = initial_value
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.
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:
// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};
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 das Array 1 000 000
Elements int
ist es viermal schneller als die normale Schleifeninitialisierung (i5, 2 Kerne, 2,3 GHz, 4 GB Speicher, 64 Bit):
loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000
void memfill(void *dest, size_t destsize, size_t elemsize) {
char *nextdest = (char *) dest + elemsize;
size_t movesize, donesize = elemsize;
destsize -= elemsize;
while (destsize) {
movesize = (donesize < destsize) ? donesize : destsize;
memcpy(nextdest, dest, movesize);
nextdest += movesize; destsize -= movesize; donesize += movesize;
}
}
int main() {
clock_t timeStart;
double runTime;
int i, a[ARR_SIZE];
timeStart = clock();
for (i = 0; i < ARR_SIZE; i++)
a[i] = 9;
runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
printf("loop runtime %f [seconds]\n",runTime);
timeStart = clock();
a[0] = 10;
memfill(a, sizeof(a), sizeof(a[0]));
runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
printf("memfill() runtime %f [seconds]\n",runTime);
return 0;
}
Wenn das Array zufällig int oder etwas mit der Größe von int ist oder die Größe Ihres Mem-Musters genau in ein int passt (d. H. Alle Nullen oder 0xA5A5A5A5), ist die beste Methode die Verwendung von memset () .
Ansonsten rufen Sie memcpy () in einer Schleife auf, die den Index verschiebt.
beispiel: int Array [10]; Memset (Array, -1, 10 * sizeof (int));
Die kurze Antwort lautet: Wenn Sie die Optimierung zur Kompilierzeit aktivieren, können Sie nichts Besseres tun:
int i,value=5,array[1000];
for(i=0;i<1000;i++) array[i]=value;
Zusätzlicher Bonus: Der Code ist tatsächlich lesbar :)
Niemand hat die Indexreihenfolge für den Zugriff auf die Elemente des initialisierten Arrays erwähnt. Mein Beispielcode wird dazu ein anschauliches Beispiel geben.
#include <iostream>
void PrintArray(int a[3][3])
{
std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
std::cout << std::endl;
}
int wmain(int argc, wchar_t * argv[])
{
int a1[3][3] = { 11, 12, 13, // The most
21, 22, 23, // basic
31, 32, 33 }; // format.
int a2[][3] = { 11, 12, 13, // The first (outer) dimension
21, 22, 23, // may be omitted. The compiler
31, 32, 33 }; // will automatically deduce it.
int a3[3][3] = { {11, 12, 13}, // The elements of each
{21, 22, 23}, // second (inner) dimension
{31, 32, 33} }; // can be grouped together.
int a4[][3] = { {11, 12, 13}, // Again, the first dimension
{21, 22, 23}, // can be omitted when the
{31, 32, 33} }; // inner elements are grouped.
PrintArray(a1);
PrintArray(a2);
PrintArray(a3);
PrintArray(a4);
// This part shows in which order the elements are stored in the memory.
int * b = (int *) a1; // The output is the same for the all four arrays.
for (int i=0; i<9; i++)
{
std::cout << b[i] << '\t';
}
return 0;
}
Die Ausgabe ist:
a11 = 11 a12 = 12 a13 = 13
a21 = 21 a22 = 22 a23 = 23
a31 = 31 a32 = 32 a33 = 33
a11 = 11 a12 = 12 a13 = 13
a21 = 21 a22 = 22 a23 = 23
a31 = 31 a32 = 32 a33 = 33
a11 = 11 a12 = 12 a13 = 13
a21 = 21 a22 = 22 a23 = 23
a31 = 31 a32 = 32 a33 = 33
a11 = 11 a12 = 12 a13 = 13
a21 = 21 a22 = 22 a23 = 23
a31 = 31 a32 = 32 a33 = 33
11 12 13 21 22 23 31 32 33
Berücksichtigen Sie für die verzögerte Initialisierung (d. H. Die Initialisierung des Klassenmitgliedskonstruktors) Folgendes:
int a[4];
unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
a[i] = 0;
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
return 0;
}
Es wird die Ausgabe 5 5 5 5 5 5 ...... bis zur Größe des gesamten Arrays geben
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]);
Nicht einmal sicher, ob es mehr funktionieren würde (das würde von der Implementierung von memcpy abhängen), aber es funktioniert, indem das ursprüngliche Element wiederholt auf das nächste kopiert wird - sogar für Arrays von Strukturen.
Ich weiß, dass der Benutzer Tarski
diese Frage auf ähnliche Weise beantwortet hat, aber ich habe ein paar weitere Details hinzugefügt. Verzeihen Sie etwas von meinem C, weil ich etwas rostig bin, da ich eher C++ verwenden möchte, aber hier geht es.
Wenn Sie die Größe des Arrays vorab kennen ...
#include <stdio.h>
typedef const unsigned int cUINT;
typedef unsigned int UINT;
cUINT size = 10;
cUINT initVal = 5;
void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray );
int main() {
UINT myArray[size];
/* Not initialized during declaration but can be
initialized using a function for the appropriate TYPE*/
arrayInitializer( myArray, size, initVal );
printArray( myArray );
return 0;
}
void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
for ( UINT n = 0; n < size; n++ ) {
myArray[n] = initVal;
}
}
void printArray( UINT* myArray ) {
printf( "myArray = { " );
for ( UINT n = 0; n < size; n++ ) {
printf( "%u", myArray[n] );
if ( n < size-1 )
printf( ", " );
}
printf( " }\n" );
}
Es gibt ein paar Vorbehalte darüber; Eine davon ist, dass UINT myArray[size];
bei der Deklaration nicht direkt initialisiert wird. Der nächste Codeblock oder Funktionsaufruf initialisiert jedoch jedes Element des Arrays mit dem gewünschten Wert. Der andere Nachteil ist, Sie müssten einen initializing function
für jede type
schreiben, die Sie unterstützen, und Sie müssten auch die printArray()
-Funktion ändern, um diese Typen zu unterstützen.
Sie können diesen Code mit einem Online-Complierer hier versuchen.