Namensräume
Varianten
Aktionen

Array-Initialisierung

Von cppreference.com
< c‎ | Sprache

Beim Initialisieren eines Objekts vom Array-Typ muss der Initialisierer entweder ein String-Literal (optional in geschweiften Klammern eingeschlossen) oder eine in geschweiften Klammern eingeschlossene Liste von Initialisierern für Array-Elemente sein.

= string-literal (1)
= { expression , ... } (2) (bis C99)
= { designator(optional) expression , ... } (2) (seit C99)
= { } (3) (seit C23)
1) String-Literal-Initialisierer für Zeichen- und Wide-Character-Arrays.
2) Komma-getrennte Liste von konstanten(bis C99) Ausdrücken, die Initialisierer für Array-Elemente sind , optional unter Verwendung von Array-Deskriptoren der Form [ constant-expression ] = (seit C99).
3) Leerer Initialisierer initialisiert jedes Element des Arrays leer.

Arrays bekannter Größe und Arrays unbekannter Größe können initialisiert werden , aber nicht VLAs(seit C99)(bis C23). Ein VLA kann nur leer initialisiert werden.(seit C23)

Alle Array-Elemente, die nicht explizit initialisiert werden, werden leer initialisiert.

Inhalt

[bearbeiten] Initialisierung aus Strings

String-Literale (optional in geschweiften Klammern eingeschlossen) können als Initialisierer für ein Array vom passenden Typ verwendet werden.

  • Gewöhnliche String-Literale und UTF-8-String-Literale(seit C11) können Arrays von jedem Zeicherntyp initialisieren (char, signed char, unsigned char).
  • L-präfixierte Wide-String-Literale können verwendet werden, um Arrays von jedem Typ zu initialisieren, der mit wchar_t kompatibel ist (ignoriert cv-Qualifikationen).
  • u-präfixierte Wide-String-Literale können verwendet werden, um Arrays von jedem Typ zu initialisieren, der mit char16_t kompatibel ist (ignoriert cv-Qualifikationen).
  • U-präfixierte Wide-String-Literale können verwendet werden, um Arrays von jedem Typ zu initialisieren, der mit char32_t kompatibel ist (ignoriert cv-Qualifikationen).
(seit C11)

Aufeinanderfolgende Bytes des String-Literals oder Wide-Zeichen des Wide-String-Literals, einschließlich des abschließenden Null-Bytes/-Zeichens, initialisieren die Elemente des Arrays.

char str[] = "abc"; // str has type char[4] and holds 'a', 'b', 'c', '\0'
wchar_t wstr[4] = L"猫"; // str has type wchar_t[4] and holds L'猫', '\0', '\0', '\0'

Wenn die Größe des Arrays bekannt ist, kann sie um eins kleiner sein als die Größe des String-Literals, in welchem Fall das abschließende Null-Zeichen ignoriert wird.

char str[3] = "abc"; // str has type char[3] and holds 'a', 'b', 'c'

Beachten Sie, dass der Inhalt eines solchen Arrays modifizierbar ist, im Gegensatz zum direkten Zugriff auf ein String-Literal mit char* str = "abc";.

[bearbeiten] Initialisierung aus Listen in geschweiften Klammern

Wenn ein Array mit einer in geschweiften Klammern eingeschlossenen Liste von Initialisierern initialisiert wird, initialisiert der erste Initialisierer in der Liste das Array-Element am Index Null (sofern kein Deskriptor angegeben ist)(seit C99), und jeder nachfolgende Initialisierer ohne Deskriptor(seit C99) initialisiert das Array-Element am Index eins größer als das vom vorherigen Initialisierer initialisierte.

int x[] = {1,2,3}; // x has type int[3] and holds 1,2,3
int y[5] = {1,2,3}; // y has type int[5] and holds 1,2,3,0,0
int z[4] = {1}; // z has type int[4] and holds 1,0,0,0
int w[3] = {0}; // w has type int[3] and holds all zeroes

Es ist ein Fehler, mehr Initialisierer als Elemente bereitzustellen, wenn ein Array bekannter Größe initialisiert wird (außer bei der Initialisierung von Zeichen-Arrays aus String-Literalen).

Ein Deskriptor bewirkt, dass der folgende Initialisierer das Array-Element initialisiert, das durch den Deskriptor beschrieben wird. Die Initialisierung wird dann fortlaufend fortgesetzt, beginnend mit dem Element nach dem durch den Deskriptor beschriebenen.

int n[5] = {[4]=5,[0]=1,2,3,4}; // holds 1,2,3,4,5
 
int a[MAX] = { // starts initializing a[0] = 1, a[1] = 3, ...
    1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
// for MAX=6,  array holds 1,8,6,4,2,0
// for MAX=13, array holds 1,3,5,7,9,0,0,0,8,6,4,2,0 ("sparse array")
(seit C99)

Beim Initialisieren eines Arrays unbekannter Größe bestimmt der größte Unterindex, für den ein Initialisierer angegeben ist, die Größe des zu deklarierenden Arrays.

[bearbeiten] Verschachtelte Arrays

Wenn die Elemente eines Arrays Arrays, Strukturen oder Unions sind, sind die entsprechenden Initialisierer in der in geschweiften Klammern eingeschlossenen Liste von Initialisierern alle Initialisierer, die für diese Member gültig sind, mit der Ausnahme, dass ihre geschweiften Klammern weggelassen werden können, wie folgt:

Wenn der verschachtelte Initialisierer mit einer öffnenden geschweiften Klammer beginnt, initialisiert der gesamte verschachtelte Initialisierer bis zu seiner schließenden geschweiften Klammer das entsprechende Array-Element.

int y[4][3] = { // array of 4 arrays of 3 ints each (4x3 matrix)
    { 1 },      // row 0 initialized to {1, 0, 0}
    { 0, 1 },   // row 1 initialized to {0, 1, 0}
    { [2]=1 },  // row 2 initialized to {0, 0, 1}
};              // row 3 initialized to {0, 0, 0}

Wenn der verschachtelte Initialisierer nicht mit einer öffnenden geschweiften Klammer beginnt, werden nur genügend Initialisierer aus der Liste genommen, um die Elemente oder Member des Unterarrays, der Struktur oder der Union zu berücksichtigen; verbleibende Initialisierer bleiben zur Initialisierung des nächsten Array-Elements übrig.

int y[4][3] = {    // array of 4 arrays of 3 ints each (4x3 matrix)
1, 3, 5, 2, 4, 6, 3, 5, 7 // row 0 initialized to {1, 3, 5}
};                        // row 1 initialized to {2, 4, 6}
                          // row 2 initialized to {3, 5, 7}
                          // row 3 initialized to {0, 0, 0}
 
struct { int a[3], b; } w[] = { { 1 }, 2 }; // array of structs
   // { 1 } is taken to be a fully-braced initializer for element #0 of the array
   // that element is initialized to { {1, 0, 0}, 0}
   // 2 is taken to be the first initialized for element #1 of the array
   // that element is initialized { {2, 0, 0}, 0}

Array-Deskriptoren können verschachtelt sein; der geklammerte konstante Ausdruck für verschachtelte Arrays folgt dem geklammerten konstanten Ausdruck für das äußere Array.

int y[4][3] = {[0][0]=1, [1][1]=1, [2][0]=1};  // row 0 initialized to {1, 0, 0}
                                               // row 1 initialized to {0, 1, 0}
                                               // row 2 initialized to {1, 0, 0}
                                               // row 3 initialized to {0, 0, 0}
(seit C99)

[bearbeiten] Hinweise

Die Reihenfolge der Auswertung von Unterausdrücken in einem Array-Initialisierer ist in C indeterministic sequenziert (aber nicht in C++ seit C++11).

int n = 1;
int a[2] = {n++, n++}; // unspecified, but well-defined behavior,
                       // n is incremented twice (in arbitrary order)
                       // a initialized to {1, 2} and to {2, 1} are both valid
puts((char[4]){'0'+n} + n++); // undefined behavior:
                              // increment and read from n are unsequenced

In C darf die geschweifte Liste eines Initialisierers nicht leer sein. C++ erlaubt leere Listen.

(bis C23)

Ein leerer Initialisierer kann zur Initialisierung eines Arrays verwendet werden.

(seit C23)
int a[3] = {0}; // valid C and C++ way to zero-out a block-scope array
int a[3] = {}; // valid C++ way to zero-out a block-scope array; valid in C since C23

Wie bei allen anderen Initialisierungen muss jeder Ausdruck in der Initialisiererliste ein konstanter Ausdruck sein, wenn Arrays mit statischer oder Thread-lokaler Speicherdauer initialisiert werden.

static char* p[2] = {malloc(1), malloc(2)}; // error

[bearbeiten] Beispiel

int main(void)
{
    // The following four array declarations are the same
    short q1[4][3][2] = {
        { 1 },
        { 2, 3 },
        { 4, 5, 6 }
    };
 
    short q2[4][3][2] = {1, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 4, 5, 6};
 
    short q3[4][3][2] = {
        {
            { 1 },
        },
        {
            { 2, 3 },
        },
        {
            { 4, 5 },
            { 6 },
        }
    };
 
    short q4[4][3][2] = {1, [1]=2, 3, [2]=4, 5, 6};
 
 
    // Character names can be associated with enumeration constants
    // using arrays with designators:
    enum { RED, GREEN, BLUE };
    const char *nm[] = {
        [RED] = "red",
        [GREEN] = "green",
        [BLUE] = "blue",
    };
}

[bearbeiten] Referenzen

  • C17-Standard (ISO/IEC 9899:2018)
  • 6.7.9/12-39 Initialisierung (S. 101-105)
  • C11-Standard (ISO/IEC 9899:2011)
  • 6.7.9/12-38 Initialisierung (S. 140-144)
  • C99-Standard (ISO/IEC 9899:1999)
  • 6.7.8/12-38 Initialisierung (S. 126-130)
  • C89/C90-Standard (ISO/IEC 9899:1990)
  • 6.5.7 Initialization