it-swarm.com.de

Arrays in C deklarieren und initialisieren

Gibt es eine Möglichkeit, zuerst ein Array in C zu deklarieren und dann zu initialisieren?

Bisher habe ich ein Array wie folgt initialisiert:

int myArray[SIZE] = {1,2,3,4....};

Aber ich muss so etwas tun

int myArray[SIZE];

myArray = {1,2,3,4....};
48
Dave H

In C99 können Sie ein zusammengesetztes Literal in Kombination mit memcpy verwenden.

memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);

(vorausgesetzt, dass die Größe der Quelle und die Größe des Ziels gleich sind). 

In C89/90 können Sie das nachahmen, indem Sie ein zusätzliches "source" -Array deklarieren

const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
29
AnT

Nein, Sie können sie nicht in einer Anweisung auf beliebige Werte setzen (sofern dies nicht als Teil der Deklaration erfolgt).

Sie können es entweder mit Code machen, etwa:

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;

oder (wenn es eine Formel gibt):

for (int i = 0; i < 100; i++) myArray[i] = i + 1;

Die andere Möglichkeit besteht darin, einige Vorlagen, die are zum Zeitpunkt der Deklaration gesetzt haben, in der Nähe zu behalten und sie zum Initialisieren Ihres Arrays zu verwenden.

static const int onceArr[]  = {  0,  1,  2,  3,  4,..., 99};
static const int twiceArr[] = {  0,  2,  4,  6,  8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));

Dies hat den Vorteil, dass es (wahrscheinlich) schneller ist und dass Sie kleinere Arrays als die Vorlagen erstellen können. Ich habe diese Methode in Situationen verwendet, in denen ich ein Array schnell neu initialisieren muss, jedoch auf einen bestimmten Status (wenn der Status nur aus Nullen bestehen würde, würde ich einfach memset verwenden).


Sie können es sogar zu einer Initialisierungsfunktion lokalisieren:

void initMyArray (int *arr, size_t sz) {
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
    memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));

Das statische Array wird (fast sicher) zur Kompilierzeit erstellt, daher entstehen keine Laufzeitkosten. Die Variable memcpy sollte blitzschnell sein, wahrscheinlich schneller als 1.229 Zuweisungsanweisungen, aber auf jeden Fall weniger Tipparbeit :-) .

13
paxdiablo

Gibt es eine Möglichkeit, zuerst zu deklarieren und dann ein Array in C initialisieren?

Es gibt! Verwenden Sie jedoch nicht die von Ihnen beschriebene Methode.

Sie können nicht mit einer durch Kommas getrennten Liste initialisieren. Dies ist nur in der Deklaration zulässig. Sie können jedoch mit ...

myArray[0] = 1;
myArray[1] = 2;
...

oder 

for(int i = 1; i <= SIZE; i++)
{
  myArray[i-1] = i;
}
4
Jacob

Dies ist ein Nachtrag zur akzeptierten Antwort von AndreyT, mit Nyans Kommentar zu nicht übereinstimmenden Array-Größen. Ich stimme nicht damit überein, dass das fünfte Element automatisch auf Null gesetzt wird. Es sollte wahrscheinlich 5 - die Zahl nach 1,2,3,4 sein. Ich würde also einen Wrapper für memcpy () vorschlagen, um einen Compile-TimeFehler zu erzeugen, wenn wir versuchen, Arrays unterschiedlicher Größe zu kopieren:

#define Memcpy(a,b) do {                    /* copy arrays */       \
    ASSERT(sizeof(a) == sizeof(b) &&        /* a static assert */   \
           sizeof(a) != sizeof((a) + 0));   /* no pointers */       \
    memcpy((a), (b), sizeof (b));           /* & unnecesary */      \
    } while (0)                             /* no return value */

Dieses Makro generiert einen Fehler bei der Kompilierung, wenn Ihr Array die Länge 1 hat. Dies ist möglicherweise eine Funktion.

Da wir ein Makro verwenden, scheint das zusammengesetzte C99-Literal ein zusätzliches Klammerpaar zu benötigen:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));

Hier ist ASSERT () eine 'statische Bestätigung'. Wenn Sie noch keine eigene haben, verwende ich auf einer Reihe von Plattformen Folgendes:

#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
2
Joseph Quinsey

Warum können Sie bei der Deklaration nicht initialisieren?

Welchen C-Compiler verwenden Sie? Unterstützt es C99?

Wenn C99 unterstützt wird, können Sie die Variable dort deklarieren, wo Sie sie benötigen, und sie bei der Deklaration initialisieren.

Die einzige Ausrede, die ich mir vorstellen kann, wenn Sie das nicht tun würden, wäre, dass Sie es deklarieren müssen, aber vorzeitig beenden, bevor Sie es verwenden. Ich vermute jedoch, dass ein solcher Code nicht so sauber organisiert ist, wie er sollte und geschrieben werden könnte, so dass es kein Problem war.

1

Es ist nicht möglich, einem Array nach der Initialisierung alle Werte gleichzeitig zuzuweisen. Die beste Alternative wäre die Verwendung einer Schleife.

for(i=0;i<N;i++)
{
     array[i] = i;
}

Sie können hart codieren und Werte wie --array[0] = 1 usw. zuweisen.

Memcpy kann auch verwendet werden, wenn Sie die Daten bereits in einem Array gespeichert haben.

0
Tush_08

Das OP hat einige wichtige Informationen aus der Frage ausgelassen und nur zu einer Antwort kommentiert.

Ich muss nach der Deklaration initialisieren, da es anders sein wird Abhängig von einer Bedingung meine ich so etwas int myArray [GRÖSSE]; if (Bedingung1) {meinArray {x1, x2, x3, ...}} else if (Bedingung2) {meinArray {y1, y2, y3, ...}}. . und so weiter...

Vor diesem Hintergrund müssen alle möglichen Arrays irgendwo in den Daten gespeichert werden, sodass kein Speicher erforderlich ist (oder gewünscht wird), sondern nur ein Zeiger und ein 2D-Array.

//static global since some compilers build arrays from instruction data
//... notably not const though so they can later be modified if needed
#define SIZE 8
static int myArrays[2][SIZE] = {{0,1,2,3,4,5,6,7},{7,6,5,4,3,2,1,0}};

static inline int *init_myArray(_Bool conditional){
  return myArrays[conditional];
}

// now you can use:
//int *myArray = init_myArray(1 == htons(1)); //any boolean expression

Die nicht-eingebettete Version ergibt die resultierende Assembly auf x86_64:

init_myArray(bool):
        movzx   eax, dil
        sal     rax, 5
        add     rax, OFFSET FLAT:myArrays
        ret
myArrays:
        .long   0
        .long   1
        .long   2
        .long   3
        .long   4
        .long   5
        .long   6
        .long   7
        .long   7
        .long   6
        .long   5
        .long   4
        .long   3
        .long   2
        .long   1
        .long   0

Für zusätzliche Bedingungen/Arrays ändern Sie einfach die 2 in myArrays in die gewünschte Anzahl und verwenden eine ähnliche Logik, um einen Zeiger auf das richtige Array zu erhalten.

0
technosaurus

Es gibt keine spezielle Möglichkeit, das Array zu initialisieren, nachdem es einmal deklariert wurde.

Es gibt nur drei Optionen:

1.) initialisiert sie in verschiedenen Zeilen:

int array[SIZE];

array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
//...
//...
//...

Aber das willst du nicht, denke ich.

2.) Initialisieren Sie sie mit einer for oder while-Schleife:

for (i = 0; i < MAX ; i++)  {
    array[i] = i;
}

Dies ist übrigens der beste Weg, um Ihr Ziel zu erreichen.

3.) Wenn Sie das Array in einer Zeile selbst initialisieren möchten, müssen Sie mindestens ein Array mit Initialisierung definieren. Kopieren Sie es dann in Ihr Zielarray, aber ich denke, dass dies keinen Vorteil bringt. In diesem Fall sollten Sie Ihr Array in einer Zeile definieren und initialisieren.

Und kann ich Sie fragen, warum Sie das wollen?

0
Kumar Alok