Differenza tra 'struct' e 'typedef struct' in C++?

In C++, c'è qualche differenza tra:

struct Foo { ... };

e

typedef struct { ... } Foo;
Soluzione

In C++, c'è solo una sottile differenza. È un retaggio del C, in cui fa la differenza.

Lo standard del linguaggio C (C89 §3.1.2.3, C99 §6.2.3, e C11 §6.2.3) impone spazi dei nomi separati per diverse categorie di identificatori, inclusi tag identifiers (per struct/union/enum) e ordinary identifiers (per typedef e altri identificatori).

Se hai appena detto

struct Foo { ... };
Foo x;

avreste un errore del compilatore, perché Foo è definito solo nello spazio dei nomi dei tag.

Dovresti dichiararlo come:

struct Foo x;

Ogni volta che vuoi fare riferimento a un Foo, dovresti sempre chiamarlo struct Foo. Questo diventa fastidioso velocemente, quindi puoi aggiungere un typedef:

struct Foo { ... };
typedef struct Foo Foo;

Ora struct Foo (nello spazio dei nomi dei tag) e semplicemente Foo (nello spazio dei nomi degli identificatori ordinari) si riferiscono entrambi alla stessa cosa, e si possono dichiarare liberamente oggetti di tipo Foo senza la parola chiave struct.


Il costrutto:

typedef struct Foo { ... } Foo;

è solo un'abbreviazione per la dichiarazione e il typedef.


Infine,

typedef struct { ... } Foo;

dichiara una struttura anonima e crea un typedef per essa. Quindi, con questo costrutto, non ha un nome nello spazio dei nomi dei tag, ma solo un nome nello spazio dei nomi typedef. Questo significa che non può nemmeno essere dichiarato in avanti. Se vuoi fare una dichiarazione forward, devi dargli un nome nello spazio dei nomi dei tag.


In C++, tutte le dichiarazioni struct/union/enum/class`` si comportano come se fossero implicitamentetypedef`'ed, finché il nome non è nascosto da un'altra dichiarazione con lo stesso nome. Vedere la risposta di Michael Burr per tutti i dettagli.

Commentari (16)

C'è una differenza, ma sottile. Guardatela in questo modo: struct Foo introduce un nuovo tipo. Il secondo crea un alias chiamato Foo (e non un nuovo tipo) per un tipo senza nome struct.

7.1.3 Lo specificatore typedef**

1 [...]

Un nome dichiarato con lo specificatore typedef diventa un typedef-name. Nell'ambito della sua dichiarazione, un typedef-name è sintatticamente equivalente ad una parola chiave e nomina il tipo associato all'identificatore nel modo descritto nella clausola 8. Un typedef-name è quindi un sinonimo di un altro tipo. Un nome tipografico non introduce un nuovo tipo come fa una dichiarazione di classe (9.1) o di enum.

8 Se la dichiarazione typedef definisce una classe (o enum) senza nome, il primo nome tipografico dichiarato dalla dichiarazione essere quel tipo di classe (o di enum) è usato per denotare il tipo di classe (o di enum) solo per scopi di collegamento (3.5). solo per scopi di collegamento (3.5). [ Esempio:

typedef struct { } *ps, S; // S is the class name for linkage purposes

Quindi, un typedef sempre è usato come segnaposto/sinonimo di un altro tipo.

Commentari (0)

Non c'è differenza in C++, ma credo che in C vi permetterebbe di dichiarare istanze della struct Foo senza farlo esplicitamente:

struct Foo bar;
Commentari (1)