HOWTO · C

Inizializza un array su 0 in C

Questo tutorial introduce diversi modi per inizializzare un array su 0 in C

In questa pagina

Per inizializzare a zero ogni elemento di un array di int al momento della dichiarazione, usa int values[5] = {0};. In C il primo elemento viene inizializzato con 0 e anche tutti gli altri elementi dell’aggregato vengono inizializzati a zero. Se l’array esiste già, assegna un valore a ogni elemento con un ciclo. memset può riempire di zeri i byte di un array, ma il riempimento dei byte non sostituisce in generale l’inizializzazione tipizzata.

Inizializzare un array a zero al momento della dichiarazione

Usa un inizializzatore quando conosci la dimensione dell’array al momento della dichiarazione. L’esempio completo seguente stampa i cinque valori inizializzati.

#include <stdio.h>

int main(void) {
    int values[5] = {0};
    for (size_t i = 0; i < sizeof values / sizeof values[0]; ++i) {
        printf("%d%s", values[i], i == 4 ? "\n" : " ");
    }
    return 0;
}
0 0 0 0 0

L’inizializzatore {0} assegna esplicitamente zero al primo elemento; l’inizializzazione dell’aggregato assegna zero anche agli elementi omessi. Puoi omettere l’inizializzatore anche per un oggetto con durata di memorizzazione statica o di thread: C lo inizializza automaticamente a zero. Un normale array locale non inizializzato ha durata di memorizzazione automatica, quindi i suoi elementi non vengono impostati automaticamente a zero. Aggiungi un inizializzatore oppure assegna i valori agli elementi prima di leggerli.

Inizializzare un array a zero con un ciclo

Un ciclo è utile quando l’array è già stato dichiarato o quando i valori vengono scelti durante l’esecuzione. Questo esempio completo usa il numero di elementi dell’array come limite del ciclo e stampa il risultato.

#include <stdio.h>

int main(void) {
    int values[5];
    size_t count = sizeof values / sizeof values[0];

    for (size_t i = 0; i < count; ++i) {
        values[i] = 0;
    }
    for (size_t i = 0; i < count; ++i) {
        printf("%d%s", values[i], i + 1 == count ? "\n" : " ");
    }
    return 0;
}
0 0 0 0 0

L’espressione sizeof funziona in questo caso perché values è un array nello stesso ambito, non un parametro puntatore. Se passi un array a una funzione, passa separatamente anche la sua lunghezza: all’interno della funzione, il parametro viene convertito in un puntatore e sizeof restituisce la dimensione del puntatore.

Usare memset con cautela

La funzione della libreria standard memset scrive lo stesso valore di byte in una regione di memoria. Includi <string.h> e usa sizeof values per coprire l’intero array nell’ambito corrente, come nell’esempio completo seguente.

#include <stdio.h>
#include <string.h>

int main(void) {
    int values[5];
    memset(values, 0, sizeof values);

    for (size_t i = 0; i < sizeof values / sizeof values[0]; ++i) {
        printf("%d%s", values[i], i == 4 ? "\n" : " ");
    }
    return 0;
}
0 0 0 0 0

Il terzo argomento indica un numero di byte, quindi sizeof values è corretto per questo array. memset non assegna un valore tipizzato a ogni elemento: scrive una rappresentazione con tutti i bit a zero. Usalo solo quando tale rappresentazione è appropriata per il tipo degli elementi e per la piattaforma. Per inizializzare portabilmente a zero il valore semantico di un array al momento della dichiarazione, preferisci {0}. Non dare per scontato che i byte a zero rappresentino un puntatore nullo o lo zero in virgola mobile in ogni implementazione di C.

Inizializzare un array con valori diversi da zero

Elenca i valori desiderati nell’inizializzatore, per esempio int values[] = {2, 4, 6};. C deduce la dimensione esterna dal numero di inizializzatori. Per un array multidimensionale, in questa forma si può omettere soltanto la dimensione esterna: int grid[][3] = {{1, 2, 3}, {4, 5, 6}};; la dimensione interna deve essere specificata.

I designatori di intervallo GNU, come int values[5] = {[0 ... 4] = 7};, sono un’estensione di GCC e non sintassi standard di C portabile. Se è importante la portabilità tra compilatori C, usa un normale elenco di inizializzatori oppure un ciclo. Un literal composto come (int[]){1, 2, 3} crea un array senza nome con durata di blocco in questo contesto di funzione; non è un’allocazione dinamica e non sostituisce una dichiarazione di array con nome come metodo generale di inizializzazione.