2011-10-29 5 views
5

Sono a conoscenza di due possibili modi per definire e utilizzare struct s:codice struct scrittura che funziona sia in C e in C++

#1 
struct person 
{ 
    char name[32]; 
    int age; 
}; 

struct person dmr = {"Dennis Ritchie", 70}; 

#2 
typedef struct 
{ 
    char name[32]; 
    int age; 
} person; 

person dmr = {"Dennis Ritchie", 70}; 

La proprietà interessante del primo modo è che sia il tipo e la variabile può avere lo stesso nome:

struct person person = {"Sam Persson", 50}; 

È idiomatico in C? È garantito il funzionamento in C++? O ci sono casi d'angolo di cui dovrei essere a conoscenza?

Nota che non mi interessano le risposte C++ pure (ad esempio "usa std::string anziché char[32]"). Questa è una domanda sulla compatibilità C/C++.

+0

Non direi che "proprietà interessante" è piuttosto oscura proprietà. È meglio mantenere i nomi dei tipi a partire da maiuscole per distinguere i nomi dei tipi e delle variabili. –

+0

L'ho contrassegnato come duplicato di [typedef struct vs struct definition] (http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions). Tecnicamente puoi considerare che non lo è (l'altra domanda riguarda solo C) ma la semantica è la stessa in C++ con la sola differenza che la ricerca troverà anche i simboli nello spazio identificatore definito dall'utente se non li trova nel spazio identificativo globale. Anche questo viene trattato nella risposta accettata (che contiene bit di C++) –

+1

Inoltre, sono ** non ** due modi di definire una 'struct', c'è un unico modo per definire una' struct' (che può avere o non un nome), e ci sono 'typedef's (che possono essere applicati a un tipo con o senza nome), ma non sono in alcun modo due modi per definire una' struct'. E ti mancano 3), combinando entrambi: 'typedef struct type {} type;' per quello che vale (che è il modo idiatico C) –

risposta

1
struct person person = {"Sam Persson", 50}; 

Non è univoco utilizzare lo stesso identificatore per un tipo e una variabile. In Unix, è tipico utilizzare una versione abbreviata per il nome della variabile, ad esempio: struct stat st, struct timeval tv, ... allo stesso modo fd è un nome tipico per una variabile descrittore di file.

3

struct sono compatibili tra C & C++ solo quando sono POD-s.

tendo a codificare qualcosa come:

struct person_st { char name[32]; int age; }; 
typedef struct person_st Person_t; 
+2

Quindi cosa sono le 'struct' non-P di C? – xanatos

+0

@xantos, 'class'es! Ma invece di 'class' scrivi' struct' e i membri sono 'public' di default in opposizione a' private' in 'class'es – Shahbaz

+0

@Shahbaz: Non ci sono classi in C. Immagino che sia ciò che intendeva xanatos. – fredoverflow

0

non sono sicuro se sarebbe del tutto corretta in C++ standard, ma ho provato con g++ -pedantic -Wall e non ho ricevuto errori o avvisi (notare che questo doesn' significa necessariamente che è completamente standard. g ++, anche con -pedantic, non passa attraverso il problema di dare un avvertimento per tutto il codice non standard.) (Qualcuno conosce le specifiche del C++ abbastanza bene da commentare se è effettivamente standard o no? ?)

La cosa con la scrittura:

struct person person = {...}; 

è che in C++, person si riferisce sia alla variabile che al tipo. In C, questo non era un problema semplicemente perché person non è il tipo (struct person è). Sebbene dal contesto, con i pochi test che ho scritto con g ++, il compilatore non ha avuto problemi a capire quando chiedo la variabile e quando per il tipo, penso che a un certo punto potrebbe confondersi. Una cosa di confusione che ho scoperto è che se si dispone di:

struct person *person = ...; 

poi sizeof(person) restituisce la dimensione della variabile, mentre per ottenere la dimensione del tipo, si dovrebbe scrivere sizeof(struct person) che vi posso assicurare, non C++ coder ricorderei di scrivere lo stuct.

È meglio evitare ogni tipo di confusione. Io di solito faccio per il codice che potrebbe essere utilizzato sia in C e C++:

typedef struct person 
{ 
    ... 
} person; 

Dare un nome alla struct che si sta typedef ndr permette al programmatore di utilizzare uno o personstruct person. Quindi, un po 'di flessibilità (per non parlare del fatto che non è necessario modificare il codice già scritto dopo lo typedef ineo struct.

+1

Per l'esempio 'sizeof'. vedere lo standard C++ §9.1 ¶2 _Se viene dichiarato un nome di classe in un ambito in cui viene dichiarata anche una variabile, funzione o enumeratore con lo stesso nome, allora quando entrambe le dichiarazioni sono nell'ambito, la classe può essere riferita solo usando un elaborato-tipo-specifier_ – ninjalj

+0

No, in C++ per il tuo primo esempio 'persona' si riferire alla variabile. –

2

dichiaro loro di avere lo stesso nome in entrambi i tag struct e spazi dei nomi identificatore globale:

#ifdef __cplusplus 
extern "C" { 
#endif 

typedef struct person 
{ 
    char name[32]; 
    int age; 
} person; 

#ifdef __cplusplus 
} 
#endif 

In uso, che non richiede l'uso del tag struct in entrambe le traduzioni C e C++:

person dmr = {"Dennis Ritchie", 70}; 

Se si preferisce il tag struct in alcuni punti, è possibile utilizzarlo anche in questo modo.

L'ovvio vantaggio è che il tipo può essere indicato da entrambi gli identificatori in entrambi gli spazi dei nomi, indipendentemente dalla lingua.