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.

C99

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.

C99

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

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.

C89

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 } };
C11

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 ).



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow