C Language
Inizializzazione
Ricerca…
Inizializzazione di variabili in C
In assenza di inizializzazione esplicita, le variabili esterne e static
sono garantite per essere inizializzate a zero; le variabili automatiche (incluse register
variabili di register
) hanno valori iniziali indeterminati 1 (cioè, garbage).
Le variabili scalari possono essere inizializzate quando vengono definite seguendo il nome con un segno di uguale e un'espressione:
int x = 1;
char squota = '\'';
long day = 1000L * 60L * 60L * 24L; /* milliseconds/day */
Per le variabili esterne e static
, l'inizializzatore deve essere un'espressione costante 2 ; l'inizializzazione viene eseguita una volta, concettualmente prima che il programma inizi l'esecuzione.
Per register
variabili automatiche e di register
, l'inizializzatore non si limita ad essere una costante: può essere qualsiasi espressione che coinvolge valori precedentemente definiti, anche chiamate di funzione.
Ad esempio, vedi lo snippet di codice qui sotto
int binsearch(int x, int v[], int n)
{
int low = 0;
int high = n - 1;
int mid;
...
}
invece di
int low, high, mid;
low = 0;
high = n - 1;
In effetti, l'inizializzazione delle variabili automatiche è solo una scorciatoia per le istruzioni di assegnazione. Quale forma preferire è in gran parte una questione di gusti. Generalmente utilizziamo assegnazioni esplicite, perché gli inizializzatori nelle dichiarazioni sono più difficili da vedere e più lontano dal punto di utilizzo. D'altra parte, le variabili dovrebbero essere dichiarate solo quando stanno per essere utilizzate, quando possibile.
Inizializzazione di un array:
Un array può essere inizializzato seguendo la sua dichiarazione con un elenco di inizializzatori racchiusi tra parentesi e separati da virgole.
Ad esempio, per inizializzare i giorni di un array con il numero di giorni in ciascun mese:
int days_of_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
(Si noti che gennaio è codificato come mese zero in questa struttura.)
Quando la dimensione dell'array viene omessa, il compilatore calcolerà la lunghezza contando gli inizializzatori, di cui ci sono 12 in questo caso.
Se ci sono meno inizializzatori per una matrice rispetto alla dimensione specificata, gli altri saranno zero per tutti i tipi di variabili.
È un errore avere troppi inizializzatori. Non esiste un modo standard per specificare la ripetizione di un inizializzatore, ma GCC ha un'estensione per farlo.
In C89 / C90 o versioni precedenti di C, non era possibile inizializzare un elemento nel mezzo di un array senza fornire tutti i valori precedenti.
Con C99 e versioni successive, gli inizializzatori designati consentono di inizializzare elementi arbitrari di un array, lasciando come valori zero tutti i valori non inizializzati.
Inizializzazione degli array di caratteri:
Gli array di caratteri sono un caso speciale di inizializzazione; una stringa può essere usata al posto della notazione di parentesi graffe e virgole:
char chr_array[] = "hello";
è una scorciatoia per il più lungo ma equivalente:
char chr_array[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
In questo caso, la dimensione dell'array è sei (cinque caratteri più il terminante '\0'
).
1 Cosa succede a una variabile dichiarata non inizializzata in C? Ha un valore?
2 Si noti che un'espressione costante è definita come qualcosa che può essere valutata in fase di compilazione. Quindi, int global_var = f();
è invalido. Un altro equivoco comune è pensare a una variabile qualificata const
come espressione costante . In C, const
significa "sola lettura", non "costante di tempo di compilazione". Quindi, definizioni globali come const int SIZE = 10; int global_arr[SIZE];
e const int SIZE = 10; int global_var = SIZE;
non sono legali in C.
Inizializzazione di strutture e matrici di strutture
Le strutture e le matrici di strutture possono essere inizializzate da una serie di valori racchiusi tra parentesi graffe, un valore per membro della struttura.
struct Date
{
int year;
int month;
int day;
};
struct Date us_independence_day = { 1776, 7, 4 };
struct Date uk_battles[] =
{
{ 1066, 10, 14 }, // Battle of Hastings
{ 1815, 6, 18 }, // Battle of Waterloo
{ 1805, 10, 21 }, // Battle of Trafalgar
};
Si noti che l'inizializzazione dell'array potrebbe essere scritta senza le parentesi interne e in passato (prima del 1990, diciamo) spesso sarebbe stata scritta senza di essi:
struct Date uk_battles[] =
{
1066, 10, 14, // Battle of Hastings
1815, 6, 18, // Battle of Waterloo
1805, 10, 21, // Battle of Trafalgar
};
Anche se questo funziona, non è un buon stile moderno - non dovresti provare a usare questa notazione nel nuovo codice e dovresti correggere gli avvertimenti del compilatore che di solito produce.
Vedi anche gli inizializzatori designati .
Utilizzando inizializzatori designati
C99 ha introdotto il concetto di inizializzatori designati. Questi ti permettono di specificare quali elementi di una matrice, struttura o unione devono essere inizializzati dai valori seguenti.
Inizializzatori designati per elementi array
Per un tipo semplice come plain int
:
int array[] = { [4] = 29, [5] = 31, [17] = 101, [18] = 103, [19] = 107, [20] = 109 };
Il termine tra parentesi quadre, che può essere qualsiasi espressione intera costante, specifica quale elemento della matrice deve essere inizializzato dal valore del termine dopo il segno =
. Gli elementi non specificati sono inizializzati di default, il che significa che gli zeri sono definiti. L'esempio mostra gli inizializzatori designati in ordine; non devono essere in ordine. L'esempio mostra lacune; quelli sono legittimi. L'esempio non mostra due diverse inizializzazioni per lo stesso elemento; anche questo è permesso (ISO / IEC 9899: 2011, §6.7.9 Inizializzazione, ¶19 L'inizializzazione deve avvenire in ordine di lista inizializzatore, ogni inizializzatore fornito per un particolare subobject che sovrascrive qualsiasi inizializzatore precedentemente elencato per lo stesso subobject ).
In questo esempio, la dimensione dell'array non è definita esplicitamente, quindi l'indice massimo specificato negli inizializzatori designati determina la dimensione dell'array, che sarebbe 21 elementi nell'esempio. Se la dimensione è stata definita, l'inizializzazione di una voce oltre la fine dell'array sarebbe un errore, come al solito.
Inizializzatori designati per strutture
È possibile specificare quali elementi di una struttura vengono inizializzati utilizzando .
notazione element
:
struct Date
{
int year;
int month;
int day;
};
struct Date us_independence_day = { .day = 4, .month = 7, .year = 1776 };
Se gli elementi non sono elencati, vengono inizializzati automaticamente (azzerati).
Inizializzatore designato per i sindacati
È possibile specificare quale elemento di unione viene inizializzato con un inizializzatore designato.
Prima dello standard C, non c'era modo di inizializzare un union
. Lo standard C89 / C90 consente di inizializzare il primo membro di un union
, quindi la scelta di quale membro è elencato per prima cosa è importante.
struct discriminated_union
{
enum { DU_INT, DU_DOUBLE } discriminant;
union
{
int du_int;
double du_double;
} du;
};
struct discriminated_union du1 = { .discriminant = DU_INT, .du = { .du_int = 1 } };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du = { .du_double = 3.14159 } };
Tieni presente che C11 ti consente di utilizzare membri di un sindacato anonimo all'interno di una struttura, in modo da non aver bisogno del nome du
nell'esempio precedente:
struct discriminated_union
{
enum { DU_INT, DU_DOUBLE } discriminant;
union
{
int du_int;
double du_double;
};
};
struct discriminated_union du1 = { .discriminant = DU_INT, .du_int = 1 };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du_double = 3.14159 };
Inizializzatori designati per array di strutture, ecc
Questi costrutti possono essere combinati per matrici di strutture contenenti elementi che sono matrici, ecc. L'uso di serie complete di parentesi assicura che la notazione sia non ambigua.
typedef struct Date Date; // See earlier in this example
struct date_range
{
Date dr_from;
Date dr_to;
char dr_what[80];
};
struct date_range ranges[] =
{
[3] = { .dr_from = { .year = 1066, .month = 10, .day = 14 },
.dr_to = { .year = 1066, .month = 12, .day = 25 },
.dr_what = "Battle of Hastings to Coronation of William the Conqueror",
},
[2] = { .dr_from = { .month = 7, .day = 4, .year = 1776 },
.dr_to = { .month = 5, .day = 14, .year = 1787 },
.dr_what = "US Declaration of Independence to Constitutional Convention",
}
};
Specifica degli intervalli negli inizializzatori di array
GCC fornisce un'estensione che consente di specificare un intervallo di elementi in una matrice a cui deve essere assegnato lo stesso inizializzatore:
int array[] = { [3 ... 7] = 29, 19 = 107 };
I punti tripli devono essere separati dai numeri per timore che uno dei punti sia interpretato come parte di un numero in virgola mobile (regola massima di munch ).