2011-01-23 28 views
36
typedef struct { 
    int hour; 
    int min; 
    int sec; 
} counter_t; 

E nel codice, vorrei inizializzare le istanze di questa struttura senza inizializzare esplicitamente ogni variabile membro. Cioè, mi piacerebbe fare qualcosa di simile:Come assegnare una struct C in linea?

counter_t counter; 
counter = {10,30,47}; //doesn't work 

per 10:30:47

piuttosto che

counter.hour = 10; 
counter.min = 30; 
counter.sec = 47; 

Non ricordo la sintassi per questo, e non l'ha fatto trova subito un modo per farlo da Google.

Grazie!

+5

Questo dovrebbe funzionare. –

+1

Sì, sembra che funzioni se faccio la dichiarazione nella stessa riga in modo simile a 'counter_t counter = {10,30,47}' ma non se la dichiarazione è stata fatta prima di questo compito. – mindthief

+5

@Oli: Perché dovrebbe funzionare? Come scritto è un incarico, non un'inizializzazione. – sth

risposta

69

inizializzazione:

counter_t c = {10, 30, 47}; 

Assignment:

c = (counter_t){10, 30, 48}; 

Quest'ultimo è chiamato "compound letterale".

+7

Nota che questo richiede GCC o C99, non un compilatore C89 o C++ rigido. –

+9

@Jeremiah: buon punto, non ho notato il tag C++. Per quanto riguarda la C89, se le persone vanno in giro a dire "C" quando intendono "C89", sono da sole per quanto mi riguarda ;-) –

+0

Bello, sì, l'ho capito anch'io - contatore usato = (counter_t) {10,30,47} che è lo stesso di quello che hai suggerito. "Compound letteral" eh? Grazie! – mindthief

7

Per motivi di manutenibilità preferisco la sintassi lista con le variabili esplicitamente individuati, come segue:

counter_t counter = {.hour = 10, .min = 30, .sec = 47}; 

o per il ritorno in linea ad esempio:

return (struct counter_t){.hour = 10, .min = 30, .sec = 47}; 

posso immaginare uno scenario in cui uno cambia l'ordine in cui sono dichiarate le variabili e, se non si identificano esplicitamente le variabili, si dovrà passare attraverso tutto il codice per correggere l'ordine delle variabili. In questo modo è più pulito e più leggibile penso

Side-note:

Come @AshleyDuncan e @MM put, questa funzionalità è stata rimossa dal ISO C++ dopo C99 https://stackoverflow.com/a/12122261/2770195, ma è supportato in gnu C++.

Così, mentre si può fare questo bene:

g++ -std=gnu++11 main.cpp -o main 

Questo genera un errore se si tenta l'esempio precedente:

# need an example. I was unable to find. Even clang++ supports it. If you know 
# one, please suggest an edit 

Se avete bisogno di compilare con un compilatore C++ con supporto per ISO C++ 11 o successivo che non riconosce questa estensione gnu, potresti dover utilizzare una classe con un semplice costruttore:

// backup workaround 
// not cool 
class gnuFTW { 
public: 
    int hour; 
    int min; 
    int sec; 
    gnuFTW(int hour, int min, int sec) { 
     this->hour = hour; 
     this->min = min; 
     this->sec = sec; 
    } 
}; 

int main(int argc, const char * argv[]) { 
    gnuFTW counter = gnuFTW(10,30,47); 
    cout << counter.hour << endl; 
    return 0; 
} 
+2

Anche questo mi piace, ma non così buono se si desidera compilare anche con un compilatore C++ come è una funzionalità solo C99 che non è supportata da C++. https://stackoverflow.com/questions/12122234/how-to-initialize-a-struct-using-the-c-style-while-using-the-g-compiler –

+0

Non lo sapeva. È un peccato, è una caratteristica così utile. L'approccio migliore che ritengo in questo caso è la soluzione di Don Doerner: https://stackoverflow.com/a/14206226/2770195. In poche parole: usa classi con variabili e un singolo inizializzatore. Non sembra una buona pratica, ma fa esattamente ciò che fanno le strutture. Andando ad aggiornare la risposta con chiarimenti, grazie per aver ricordato – MuhsinFatih

+0

Sono confuso, ho appena compilato un esempio con l'opzione -gnu ++ 11: https://1drv.ms/i/s!ArNqKg0GFwIE0HVGDPPHvpEgaGrh. Mi sto perdendo qualcosa? – MuhsinFatih