Inizializzazione di una struttura su 0


116

Se ho una struttura come questa:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Quale sarebbe il modo più semplice per inizializzare questa struttura su 0? Sarebbe sufficiente quanto segue?

myStruct _m1 = {0};

o Avrei bisogno di inizializzare esplicitamente ogni membro a 0?

myStruct _m2 = {0,0};

Risposte:


142

Il primo è il più semplice ( richiede meno battitura ) ed è garantito che funzioni, tutti i membri saranno impostati su 0[Rif 1] .
Il secondo è più leggibile.

La scelta dipende dalle preferenze dell'utente o da quella richiesta dallo standard di codifica.

[Rif 1] Riferimento C99 Standard 6.7.8.21:

Se ci sono meno inizializzatori in un elenco racchiuso tra parentesi quadre rispetto agli elementi o membri di un aggregato, o meno caratteri in una stringa letterale utilizzata per inizializzare un array di dimensioni note rispetto agli elementi dell'array, il resto dell'aggregato deve essere inizializzati implicitamente allo stesso modo degli oggetti che hanno una durata di archiviazione statica.

Buona lettura:
C e C ++: inizializzazione parziale della struttura automatica


9
Inoltre, sto usando = {};Tuttavia non sono sicuro che sia valido.
William Entriken

15
Le parentesi graffe vuote @FullDecent per l'inizializzazione sono un'estensione GNU.
A3f

2
@ alias65536 La domanda è contrassegnata come C non C ++.
a3f

3
Ho ricevuto un errore: "parentesi graffe mancanti attorno all'inizializzatore [-Werror = missing-braces]" probabilmente a causa di un array di membri: /
DrumM

3
@Edenia. Non sono d'accordo. So già cosa foo = {0}significa. Se vedessi foo = ZERO_FULL, dovrei grep per la definizione di ZERO_FULL.
Andrew Bainbridge

32

Se i dati sono una variabile statica o globale, sono riempiti con zero per impostazione predefinita, quindi dichiaralo myStruct _m;

Se i dati sono una variabile locale o una zona allocata nell'heap, cancellalo con il seguente memset:

memset(&m, 0, sizeof(myStruct));

I compilatori attuali (ad esempio le versioni recenti di gcc) lo ottimizzano abbastanza bene nella pratica. Funziona solo se tutti i valori zero (includono puntatori nulli e zero in virgola mobile) sono rappresentati come tutti i bit zero, il che è vero su tutte le piattaforme che conosco (ma lo standard C consente implementazioni in cui questo è falso; Non conosco tale implementazione) .

Potresti forse codificare myStruct m = {};o myStruct m = {0};(anche se il primo membro di myStructnon è uno scalare).

La mia sensazione è che l'uso memsetper le strutture locali sia il migliore e trasmette meglio il fatto che in fase di esecuzione, qualcosa deve essere fatto (mentre di solito, i dati globali e statici possono essere intesi come inizializzati in fase di compilazione, senza alcun costo in fase di esecuzione) .


7
Non c'è alcuna garanzia che l'impostazione di tutti i byte della struttura su 0sarà equivalente all'inizializzazione di tutti i membri della struttura con 0tuttavia. Su molte piattaforme questo sarà vero, ma non universalmente.
Sander De Dycker

1
Puoi condividere un esempio, Sander? Vera curiosità. (Ovviamente, non universalmente vero non significa necessariamente che ci sia un'eccezione facile da spiegare, ma se c'è ...)
Steven Fisher,

2
Lo standard C consente che il puntatore nullo (o un numero a virgola mobile zero) venga rappresentato in memoria da qualcos'altro oltre a tutti i bit zero. Pochissime e strane implementazioni lo stanno facendo (non posso nominarne nessuna).
Basile Starynkevitch

-1, potresti trovare brutta l'inizializzazione richiesta dall'OP, ma è esattamente ciò che è previsto dallo standard e può essere facilmente ottimizzato da tutti i compilatori. Quindi, il modulo {}non è C valido ma disponibile solo in C ++.
Jens Gustedt

7
@Steven: posso solo pensare a piattaforme oscure e / o vecchie. La C FAQ ha un elenco di piattaforme che avevano un NULLpuntatore che non era tutto 0bit: c-faq.com/null/machexamp.html . E poi c'è la possibilità che la piattaforma non stia utilizzando IEEE 754 per rappresentare valori in virgola mobile, ma usi qualche altra rappresentazione che non ha un valore di tutti i 0bit 0.0, ma devo ammettere che non conosco alcuna piattaforma del genere.
Sander De Dycker

19

Vedere §6.7.9 Inizializzazione:

21 Se ci sono meno inizializzatori in un elenco racchiuso tra parentesi graffe rispetto agli elementi o membri di un aggregato, o meno caratteri in un valore letterale stringa utilizzato per inizializzare un array di dimensioni note rispetto agli elementi dell'array, il resto dell'aggregato deve essere inizializzato implicitamente allo stesso modo degli oggetti che hanno una durata di memorizzazione statica.

Quindi, sì, funzionano entrambi. Si noti che in C99 è possibile utilizzare anche un nuovo modo di inizializzazione, chiamato inizializzazione designata:

myStruct _m1 = {.c2 = 0, .c1 = 1};

In particolare questo è già C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Importante per obiettivi di elaborazione del segnale specifici)
Tobias
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.