C e C ++: inizializzazione parziale della struttura automatica

Ad esempio, se somestruct ha tre membri interi, ho sempre pensato che fosse OK farlo in C (o C ++):

 somestruct s = {123,}; 

Il primo membro verrebbe inizializzato a 123 e gli ultimi due sarebbero inizializzati a 0. Faccio spesso la stessa cosa con gli array automatici, scrivendo int arr[100] = {0,}; in modo che tutti gli interi di un array siano inizializzati a zero.

Recentemente ho letto nel manuale di riferimento di GNU C che:

Se non si inizializza una variabile di struttura, l’effetto dipende dal fatto che abbia o meno una memoria statica (vedere Specifier della class di memoria). Se lo è, i membri con tipi interi vengono inizializzati con 0 e i membri del puntatore vengono inizializzati su NULL; altrimenti, il valore dei membri della struttura è indeterminato.

Qualcuno può dirmi cosa dicono gli standard C e C ++ in merito alla struttura automatica parziale e all’inizializzazione automatica dell’array? Faccio il codice sopra in Visual Studio senza problemi, ma voglio essere compatibile con gcc / g ++ e forse anche con altri compilatori. Grazie

La documentazione di gcc collegata non parla di inizializzazione parziale , ma parla solo di inizializzazione (completa) o nessuna inizializzazione .

Cos’è l’inizializzazione parziale?

Gli standard non definiscono l’inizializzazione parziale degli oggetti, o c’è l’inizializzazione completa o l’inizializzazione senza authorization. L’inizializzazione parziale è una terminologia non standard che comunemente fa riferimento a una situazione in cui vengono forniti alcuni inizializzatori ma non tutti, ad esempio: meno inizializzatori rispetto alla dimensione della matrice o al numero di elementi della struttura inizializzati.

Esempio:

 int array[10] = {1,2}; //Case 1:Partial Initialization 

Che cos’è l’inizializzazione (completa) o nessuna inizializzazione?

Inizializzazione significa fornire un valore iniziale alla variabile che viene creata nello stesso momento in cui viene creata. vale a dire: nella stessa dichiarazione di codice.

Esempio:

 int array[10] = {0,1,2,3,4,5,6,7,8,9}; //Case 2:Complete Initialization int array[10]; //Case 3:No Initialization 

Il paragrafo citato descrive il comportamento per il Case 3 .

Le regole relative all’inizializzazione parziale ( Case 1 ) sono ben definite dallo standard e queste regole non dipendono dal tipo di archiviazione della variabile da inizializzare.
AFAIK, tutti i compilatori mainstream hanno il 100% di conformità a queste regole.


Qualcuno può dirmi cosa dicono gli standard C e C ++ in merito alla struttura automatica parziale e all’inizializzazione automatica dell’array?

Gli standard C e C ++ garantiscono che anche se un array intero si trova sulla memoria automatica e se ci sono meno inizializzatori in una lista chiusa, gli elementi non inizializzati devono essere inizializzati su 0 .

C99 Standard 6.7.8.21

Se sono presenti meno inizializzatori in un elenco racchiuso tra parentesi graffe rispetto a elementi o membri di un aggregato, o meno caratteri in un letterale stringa utilizzato per inizializzare un array di dimensioni note rispetto a quelli presenti nell’array, il resto dell’aggregato deve essere essere inizializzato implicitamente come oggetti con durata di archiviazione statica.


In C ++ le regole sono indicate con una piccola differenza.

C ++ 03 Standard 8.5.1 Aggregati
Par. 7:

Se nell’elenco sono presenti meno inizializzatori di quanti ne siano membri nell’aggregato, ciascun membro non inizializzato esplicitamente deve essere inizializzato in base al valore (8.5). [Esempio:

  struct S { int a; char* b; int c; }; S ss = { 1, "asdf" }; 

inizializza ss.a con 1 , ss.b con "asdf" e ss.c con il valore di un’espressione del modulo int() , cioè 0 . ]

Mentre Value Initialization è definito in,
C ++ 03 8.5 Inizializzatori
Paragrafo 5:

Per inizializzare il valore di un object di tipo T significa:
– se T è un tipo di class (clausola 9) con un costruttore dichiarato dall’utente (12.1), viene chiamato il costruttore predefinito per T (e l’inizializzazione è mal formata se T non ha un costruttore predefinito accessibile);
– se T è un tipo di class non-union senza un costruttore dichiarato dall’utente, allora ogni membro di dati non statici e componente di class base di T è inizializzato a valore;
– se T è un tipo di matrice, ogni elemento viene inizializzato in base al valore;
– altrimenti, l’object è inizializzato a zero

In C, gli oggetti non vengono mai parzialmente inizializzati: se una parte di essi viene inizializzata, l’intero object (e tutti gli oggetti secondari in modo ricorsivo) vengono inizializzati. Se non viene fornito alcun inizializzatore esplicito, gli elementi vengono inizializzati su “zero del tipo appropriato”.

La citazione nella tua domanda si riferisce a quando l’inizializzatore per l’intero object è completamente escluso, non quando un sub-object non ha un inizializzatore. Ad esempio, supponendo che arr abbia una durata di archiviazione automatica, allora questo:

 int arr[100] = { 123 }; 

inizializza arr[0] a 123 e ogni altro elemento di arr in 0 . Mentre questo:

 int arr[100]; 

lascia ogni elemento di arr non inizializzato. È quest’ultimo caso che la citazione è in riferimento a.

le versioni più recenti di gcc consentono anche di inizializzare e zeromem “parzialmente” contemporaneamente:

 typedef struct{ int a,b,c; }T; T s = {0, .b=5}; 

i membri della struct avranno ora questi valori: a=0, b=5, c=0

Non ho informazioni sul fatto che altri compilatori lo consentano o no: p

Se la variabile è globale e statica, alloca nell’area globale dei file binari che viene inizializzata a zero. Se la variabile è locale, alloca nello stack, il compilatore non inizializza la memoria nello stack (una versione di debug può essere inizializzata, ma la versione di rilascio non lo fa mai)

Se la variabile è allocata in Heap, il compilatore non lo inizializza neanche.

 // You can use something like this: typedef struct { ...; ...; } somestruct; // Declaration of struct somestruct st; // Initialising with 0. It does not depend on the size of the // structure and the number of elements in it. // memset() initialisation doesn't care if struct is static or dynamic. // but don't forget to use st instead &st to dynamic. memset(&st, 0, sizeof(somestruct));