it-swarm.dev

Wie initialisiere ich alle Mitglieder eines Arrays auf den gleichen Wert?

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?

855
Matt

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.)

1116
aib

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

364
qrdl

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.

Edit: mögliche nützliche Erweiterungen

(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. 

169
mouviciel

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.

61
Frank Szczerba

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.

Mehr zu dieser Technik finden Sie hier und hier .

47
abelenky
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.

21
Tarski

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.

11
plinth

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:

C-Erweiterungen

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. 

7
humble_guru

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};
5
warren

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:

  • initialisiere erstes Element des Arrays (üblicher Weg)
  • kopierteil, das in einen nicht gesetzten Teil gesetzt wurde, wobei die Größe bei jedem nächsten Kopiervorgang verdoppelt wird

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;
}
4
Maciej

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.

4
ddimitrov
  1. Wenn Ihr Array als statisch oder global deklariert ist, haben alle Elemente.
  2. Einige Compiler setzen den Array-Standard im Debug-Modus auf 0. 
  3. Der Standardwert kann einfach auf 0 gesetzt werden: Int array [10] = {0}; 
  4. Für andere Werte haben Sie jedoch memset () oder loop verwendet;

beispiel: int Array [10]; Memset (Array, -1, 10 * sizeof (int));

1
Hannah Zhang

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 :)

1
JWDN

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
1
hkBattousai

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;
0
nikc
#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

0
Dadhich Sourav

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.

0
Mike

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.

0
Francis Cugler