Inizializzazione di tipi di aggregazione
Un tipo aggregato può essere una struttura, un'unione o un tipo di matrice. Se un tipo aggregato contiene membri di tipi aggregati, le regole di inizializzazione vengono applicate in modo ricorsivo.
Sintassi
initializer
:
{
initializer-list
}
/* Per l'inizializzazione aggregata */
{
initializer-list
, }
initializer-list
:
initializer
initializer-list
,
initializer
initializer-list
è un elenco di inizializzatori separati da virgole. Ogni inizializzatore presente nell'elenco è un'espressione costante o un elenco di inizializzatori. Di conseguenza, gli elenchi di inizializzatori possono essere annidati. Questo modulo è utile per inizializzare i membri di aggregazione di un tipo aggregato, come illustrato negli esempi riportati in questa sezione. Tuttavia, se l'inizializzatore di un identificatore automatico è un'espressione singola, non è necessario che sia un'espressione costante. È sufficiente che abbia un tipo appropriato per l'assegnazione all'identificatore.
Per ogni elenco di inizializzatori, i valori delle espressioni costanti vengono assegnati, in ordine, ai membri corrispondenti della variabile di aggregazione.
Se initializer-list
ha meno valori di un tipo di aggregazione, i membri o gli elementi rimanenti del tipo di aggregazione vengono inizializzati su 0. Il valore iniziale di un identificatore automatico non esplicitamente inizializzato non è definito. Se initializer-list
ha più valori di un tipo di aggregazione, viene restituito un errore. Queste regole si applicano a ogni elenco di inizializzatori incorporati e all'aggregazione nel suo complesso.
L'inizializzatore di una struttura è un'espressione dello stesso tipo o un elenco di inizializzatori per i relativi membri racchiusi tra parentesi graffe ({ }
). I membri del campo di bit senza nome non vengono inizializzati.
Quando viene inizializzata un'unione, initializer-list
deve essere una singola espressione costante. Il valore dell'espressione costante viene assegnato al primo membro dell'unione.
In caso di una matrice di dimensione sconosciuta, il numero di inizializzatori ne determina la dimensione e il relativo tipo diventa completo. Non è possibile specificare la ripetizione di un inizializzatore in C o di inizializzare un elemento al centro di una matrice senza fornire anche tutti i valori precedenti. Se si desidera che questa operazione sia presente nel programma, è necessario scrivere la routine in linguaggio assembly.
Il numero di inizializzatori può impostare le dimensioni della matrice:
int x[ ] = { 0, 1, 2 }
Se si specifica la dimensione e si indica un numero di inizializzatori errato, il compilatore genera un errore.
Sezione specifica Microsoft
Le dimensioni massime per una matrice sono definite da size_t
.
Fine sezione specifica Microsoft
Esempi
In questo esempio sono illustrati gli inizializzatori di una matrice.
int P[4][3] =
{
{ 1, 1, 1 },
{ 2, 2, 2 },
{ 3, 3, 3,},
{ 4, 4, 4,},
};
Questa istruzione dichiara P
come matrice quattro per tre e inizializza gli elementi della prima riga su 1, gli elementi della seconda riga a 2 e così via, fino alla quarta riga. L'elenco di inizializzatori per la terza e la quarta riga contiene virgole dopo l'ultima espressione costante. Anche l'ultimo elenco di inizializzatori ({4, 4, 4,},
) è seguito da una virgola. Queste virgole aggiuntive sono consentite ma non sono necessarie. Sono necessarie solo virgole che separano le espressioni costanti l'una dall'altra e le virgole che separano un elenco di inizializzatori da un altro.
Se un membro aggregato non ha un elenco di inizializzatori incorporati, i valori vengono assegnati, in ordine, a ogni membro del subaggregato. Pertanto, l'inizializzazione nell'esempio precedente è equivalente all'esempio seguente:
int P[4][3] =
{
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4
};
Le parentesi graffe possono anche essere visualizzate intorno a singoli inizializzatori nell'elenco e contribuirebbero a chiarire l'esempio.
Quando si inizializza una variabile di aggregazione, è necessario utilizzare le parentesi graffe e gli elenchi di inizializzatori correttamente. Nell'esempio seguente viene illustrata più dettagliatamente l'interpretazione delle parentesi graffe da parte del compilatore:
typedef struct
{
int n1, n2, n3;
} triplet;
triplet nlist[2][3] =
{
{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }, /* Row 1 */
{ { 10,11,12 }, { 13,14,15 }, { 16,17,18 } } /* Row 2 */
};
In questo esempio, nlist
viene dichiarato come una matrice di strutture due per tre, in cui ogni struttura dispone di tre membri. La riga 1 dell'inizializzazione assegna valori alla prima riga di nlist
, come illustrato di seguito:
La prima parentesi graffa sinistra sulla riga 1 indica al compilatore che l'inizializzazione del primo membro di aggregazione di
nlist
(ovveronlist[0]
) sta iniziando.La seconda parentesi graffa sinistra indica che l'inizializzazione del primo membro di aggregazione di
nlist[0]
(ovvero la struttura presente innlist[0][0]
) sta iniziando.La prima parentesi graffa destra termina l'inizializzazione della struttura
nlist[0][0]
; la parentesi graffa sinistra successiva avvia l'inizializzazione dinlist[0][1]
.Il processo continua fino alla fine della riga, dove la parentesi graffa destra di chiusura termina l'inizializzazione di
nlist[0]
.
Con modalità simili, la riga 2 assegna valori alla seconda riga di nlist
. Sono necessari i set esterni di parentesi graffe che racchiudono gli inizializzatori nelle righe 1 e 2. La costruzione seguente, nella quale le parentesi graffe esterne sono omesse, genererebbe un errore:
triplet nlist[2][3] = /* THIS CAUSES AN ERROR */
{
{ 1, 2, 3 },{ 4, 5, 6 },{ 7, 8, 9 }, /* Line 1 */
{ 10,11,12 },{ 13,14,15 },{ 16,17,18 } /* Line 2 */
};
In questa costruzione, la prima parentesi graffa sinistra sulla riga 1 avvia l'inizializzazione di nlist[0]
, che è una matrice di tre strutture. I valori 1, 2 e 3 vengono assegnati ai tre membri della prima struttura. Quando viene rilevata la successiva parentesi graffa destra (dopo il valore 3), l'inizializzazione di nlist[0]
è completa e le due strutture rimanenti della matrice a tre strutture vengono automaticamente inizializzate su 0. In modo simile { 4,5,6 }
inizializza la prima struttura presente nella seconda riga di nlist
. Le due strutture rimanenti di nlist[1]
vengono impostate su 0. Quando il compilatore rileva il successivo elenco di inizializzatori ({ 7,8,9 }
) prova a inizializzare nlist[2]
. Poiché nlist
dispone di due sole righe, questo tentativo provoca un errore.
Nell'esempio seguente, i tre membri int
di x
vengono inizializzati, rispettivamente, su 1, 2 e 3.
struct list
{
int i, j, k;
float m[2][3];
} x = {
1,
2,
3,
{4.0, 4.0, 4.0}
};
list
Nella struttura, i tre elementi della prima riga di m
vengono inizializzati su 4.0. Gli elementi della riga rimanente di m
vengono inizializzati su 0,0 per impostazione predefinita.
union
{
char x[2][3];
int i, j, k;
} y = { {
{'1'},
{'4'}
}
};
La variabile di unione y
, presente in questo esempio, viene inizializzata. Il primo elemento dell'unione è una matrice, pertanto l'inizializzatore è un inizializzatore di aggregazione. L'elenco di inizializzatori {'1'}
assegna i valori alla prima riga della matrice. Poiché nell'elenco viene visualizzato un solo valore, l'elemento presente nella prima colonna viene inizializzato al carattere 1
e i due elementi rimanenti nella riga vengono inizializzati sul valore 0 per impostazione predefinita. Analogamente, il primo elemento della seconda riga di x
viene inizializzato al carattere 4
, mentre i due elementi rimanenti nella riga vengono inizializzati sul valore 0.