2009-10-21 9 views
34

Ho trovato qualche codice di inizializzazione della struttura ieri che mi ha lanciato per un ciclo. Ecco un esempio:Inizializzazione della struct C mediante etichette. Funziona, ma come?

typedef struct { int first; int second; } TEST_STRUCT; 
void testFunc() { 
    TEST_STRUCT test = { 
     second: 2, 
     first: 1 
    }; 
    printf("test.first=%d test.second=%d\n", test.first, test.second); 
} 

Sorprendentemente (per me), ecco l'output:

-> testFunc 
test.first=1 test.second=2 

Come si può vedere, la struct viene inizializzato correttamente. Non ero consapevole che le dichiarazioni etichettate potessero essere usate in quel modo. Ho visto molti altri modi di fare l'inizializzazione della struct, ma non ho trovato alcun esempio di questo tipo di inizializzazione della struct su nessuna delle domande frequenti online di C. Qualcuno è a conoscenza di come/perché funziona?

risposta

25

Qui è la sezione del manuale gcc che spiega la sintassi di inizializzatori designati per entrambe le strutture e array:

In un inizializzatore struttura, specificare il nome di un campo per inizializzare con '.fieldname = 'prima del valore dell'elemento. Ad esempio, dato il seguente struttura,

struct point { int x, y; }; 

seguente inizializzazione

struct point p = { .y = yvalue, .x = xvalue }; 

è equivalente a

struct point p = { xvalue, yvalue }; 

Un'altra sintassi che ha lo stesso significato, obsoleto dal GCC 2.5, è 'nome campo:', come mostrato qui:

struct point p = { y: yvalue, x: xvalue }; 

La pagina pertinente può essere trovata here.

Il compilatore deve avere una documentazione simile.

+2

eccellente, che la documentazione spiega chiaramente la sintassi: Un'altra sintassi che ha lo stesso significato, obsoleto dal GCC 2.5, è 'nomecampo:', come illustrato di seguito: struct punto p = {y: yvalue, x: xvalue}; –

+1

@AndrewCottrell, questa sintassi "fieldname:" sembra così naturale (e preferibile) per me, qualsiasi idea sul perché dovrebbe essere considerata obsoleta? – rick

+1

@rick la sintassi "fieldname:" è un'estensione gcc e non ha mai fatto parte di alcuno standard ISO C. – sigjuice

5

Non sono realmente "istruzioni etichettate", ma un modo per fornire i valori iniziali ai campi denominati nella struttura.

Gcc dà un avvertimento circa "l'uso obsoleto di inizializzatore designato con ':'", e in C99 si dovrebbe invece scrivere:

TEST_STRUCT test = { 
     .second = 2, 
     .first = 1 
    }; 
32

Questi sono né etichette, né campi di bit.

Questa è una sintassi per inizializzare membri della struttura risalenti ai giorni prima di C99. Non è standardizzato ma disponibile ad es. gcc.

typedef struct { int y; int x; } POINT; 
POINT p = { x: 1, y: 17 }; 

In C99, la sintassi per l'inizializzazione specifici membri struct è stato introdotto per la prima volta in uno standard, ma sembra un po 'diverso:

typedef struct { int y; int x; } POINT; 
POINT p = { .x = 1, .y = 17 }; 
+0

Sì, ero a conoscenza del formato di inizializzazione designato. Sfortunatamente quel formato non è compatibile con C++! (Non nei miei test comunque.) Grazie per la risposta però. Buono a sapersi questo non è standardizzato. –

+6

@Andrew non hai mai detto nulla di C++ nella tua domanda – horseyguy

3

Che sintassi non è definito dalla C standard . Sezione 6.7.8 Initialization dice

  designation: 
       designator-list = 
     designator-list: 
       designator 
       designator-list designator 
     designator: 
       [ constant-expression ] 
       . identifier 

Se il compilatore accetta una designazione con i due punti senza un messaggio di diagnostica significa che il compilatore non è (o non è configurato per essere) Conforme agli standard.

9

Sì, come indicato sopra, questi sono gli inizializzatori designati, che sono C standard, anche se è necessario passare all'utilizzo di punti anziché di due punti. E come noti, la maggior parte dei libri là fuori sono ancora bloccati da qualche parte intorno al 1984 nella loro sintassi e mancano di menzionarli. Ulteriori informazioni:

- Quando si utilizzano gli inizializzatori designati, tutto ciò che non è specificato viene inizializzato a zero. Questo aiuta con una superficie le strutture, come ad esempio:

typedef struct { 
    double a, b, c, d, e; 
    char label[100]; 
} too_many_type; 

too_many_type tm = {.a = 1, .e = 2, .b=1.5}; 
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5); 
assert(!strlen(label)); 

--Also, è possibile utilizzare la forma letterale composto di utilizzare questa forma su una linea non di inizializzazione, ad esempio:

too_many_type tm2; 
tm2 = (too_many_type) {.a = 3, .e=6}; 

Questi sono realmente grandi caratteristiche, e sono supportate da ogni compilatore C a cui posso pensare, visto che è lo standard. È un peccato che non siano così famosi.

+1

La sintassi alternativa (utilizzando i due punti) sembra così naturale e preferibile per me, potresti chiarire il motivo per cui dovremmo passare all'utilizzo di punti anziché di due punti? – rick

Problemi correlati