Array initialization
Beim Initialisieren eines Objekts vom Array -Typ muss der Initialisierer entweder ein String-Literal (wahlweise in geschweiften Klammern eingeschlossen) oder eine in geschweiften Klammern eingeschlossene Liste von Initialisierungen für Array-Elemente sein:
=
string-literal
|
(1) | ||||||||
=
{
expression
,
...
}
|
(2) | (bis C99) | |||||||
=
{
designator
(optional)
expression
,
...
}
|
(2) | (seit C99) | |||||||
=
{
}
|
(3) | (seit C23) | |||||||
[
constant-expression
]
=
(seit C99)
Arrays bekannter Größe und Arrays unbekannter Größe können initialisiert werden , aber nicht VLAs (since C99) (until C23) . Ein VLA kann nur leer-initialisiert werden. (since C23)
Alle Array-Elemente, die nicht explizit initialisiert werden, sind empty-initialized .
Inhaltsverzeichnis |
Initialisierung aus Zeichenketten
String-Literal (optional in geschweiften Klammern eingeschlossen) kann 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 jedes Zeichentyps initialisieren ( char , signed char , unsigned char )
- L-präfixierte breite String-Literale können zur Initialisierung von Arrays jedes mit (unter Ignorierung von CV-Qualifizierern) kompatiblen Typs verwendet werden wchar_t
|
(seit C11) |
Aufeinanderfolgende Bytes des Zeichenkettenliterals oder Breitzeichen des Breiten-Zeichenkettenliterals, einschließlich des abschließenden Nullbytes/-zeichens, initialisieren die Elemente des Arrays:
char str[] = "abc"; // str hat den Typ char[4] und enthält 'a', 'b', 'c', '\0' wchar_t wstr[4] = L"猫"; // str hat den Typ wchar_t[4] und enthält 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, wobei das abschließende Nullzeichen ignoriert wird:
char str[3] = "abc"; // str hat den Typ char[3] und enthält 'a', 'b', 'c'
Beachten Sie, dass der Inhalt eines solchen Arrays veränderbar ist, im Gegensatz zum direkten Zugriff auf ein String-Literal mit char * str = "abc" ; .
Initialisierung aus geschweiften Klammern-Listen
Wenn ein Array mit einer in geschweiften Klammern eingeschlossenen Liste von Initialisierern initialisiert wird, initialisiert der erste Initialisierer in der Liste das Array-Element bei Index Null (sofern kein Designator angegeben ist) (seit C99) , und jeder nachfolgende Initialisierer ohne Designator (seit C99) initialisiert das Array-Element bei einem Index, der um eins größer ist als der durch den vorherigen Initialisierer initialisierte Index.
int x[] = {1,2,3}; // x hat den Typ int[3] und enthält 1,2,3 int y[5] = {1,2,3}; // y hat den Typ int[5] und enthält 1,2,3,0,0 int z[4] = {1}; // z hat den Typ int[4] und enthält 1,0,0,0 int w[3] = {0}; // w hat den Typ int[3] und enthält ausschließlich Nullen
Es ist ein Fehler, mehr Initialisierer als Elemente bereitzustellen, wenn ein Array bekannter Größe initialisiert wird (außer bei der Initialisierung von Zeichenarrays aus String-Literalen).
|
Ein Designator bewirkt, dass der folgende Initialisierer das durch den Designator beschriebene Array-Element initialisiert. Die Initialisierung setzt sich dann vorwärts in der Reihenfolge fort, beginnend mit dem nächsten Element nach dem durch den Designator beschriebenen Element. 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 Index, für den ein Initialisierer angegeben ist, die Größe des deklarierten Arrays.
Verschachtelte Arrays
Wenn die Elemente eines Arrays selbst Arrays, Structs oder Unions sind, sind die entsprechenden Initialisierer in der geschweiften Klammer-Initialisiererliste alle Initialisierer, die für diese Mitglieder gültig sind, mit der Ausnahme, dass ihre geschweiften Klammern wie folgt weggelassen werden können:
Wenn der verschachtelte Initialisierer mit einer öffnenden Klammer beginnt, initialisiert der gesamte verschachtelte Initialisierer bis zu seiner schließenden Klammer das entsprechende Array-Element:
int y[4][3] = { // Array von 4 Arrays mit je 3 ints (4x3 Matrix) { 1 }, // Zeile 0 initialisiert mit {1, 0, 0} { 0, 1 }, // Zeile 1 initialisiert mit {0, 1, 0} { [2]=1 }, // Zeile 2 initialisiert mit {0, 0, 1} }; // Zeile 3 initialisiert mit {0, 0, 0}
Wenn der verschachtelte Initialisierer nicht mit einer öffnenden Klammer beginnt, werden nur genügend Initialisierer aus der Liste entnommen, um die Elemente oder Mitglieder des Unter-Arrays, der Struktur oder der Union zu berücksichtigen; alle verbleibenden Initialisierer werden zur Initialisierung des nächsten Array-Elements verwendet:
int y[4][3] = { // Array von 4 Arrays mit je 3 ints (4x3 Matrix) 1, 3, 5, 2, 4, 6, 3, 5, 7 // Zeile 0 initialisiert mit {1, 3, 5} }; // Zeile 1 initialisiert mit {2, 4, 6} // Zeile 2 initialisiert mit {3, 5, 7} // Zeile 3 initialisiert mit {0, 0, 0} struct { int a[3], b; } w[] = { { 1 }, 2 }; // Array von Strukturen // { 1 } wird als vollständig geklammerter Initialisierer für Element #0 des Arrays betrachtet // dieses Element wird initialisiert mit { {1, 0, 0}, 0} // 2 wird als erster Initialisierer für Element #1 des Arrays betrachtet // dieses Element wird initialisiert mit { {2, 0, 0}, 0}
|
Array-Designatoren können geschachtelt werden; der eingeklammerte konstante Ausdruck für verschachtelte Arrays folgt dem eingeklammerte 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) |
Hinweise
Die Auswertungsreihenfolge von Teilausdrücken in einem Array-Initialisierer ist in C indeterminiert sequenziert (aber nicht in C++ seit C++11):
int n = 1; int a[2] = {n++, n++}; // nicht spezifiziert, aber wohldefiniertes Verhalten, // n wird zweimal inkrementiert (in beliebiger Reihenfolge) // a wird entweder mit {1, 2} oder {2, 1} initialisiert, beides ist gültig puts((char[4]){'0'+n} + n++); // undefiniertes Verhalten: // Inkrement und Lesen von n sind nicht sequenziert
|
In C darf die geschweifte Liste eines Initialisierers nicht leer sein. C++ erlaubt leere Listen: |
(until C23) |
|
Ein leerer Initialisierer kann zur Initialisierung eines Arrays verwendet werden: |
(since C23) |
int a[3] = {0}; // gültige C- und C++-Methode, um einen Blockbereichs-Array zu nullen int a[3] = {}; // gültige C++-Methode, um einen Blockbereichs-Array zu nullen; gültig in C seit C23
Wie bei allen anderen Initialisierungen muss jeder Ausdruck im Initialisierer eine konstante Expression sein, wenn Arrays mit statischer oder thread-lokaler Speicherdauer initialisiert werden:
Beispiel
int main(void) { // Die folgenden vier Array-Deklarationen sind identisch 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}; // Zeichennamen können Enumerationskonstanten zugeordnet werden // unter Verwendung von Arrays mit Designatoren: enum { RED, GREEN, BLUE }; const char *nm[] = { [RED] = "red", [GREEN] = "green", [BLUE] = "blue", }; }
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 Initialisierung