Quelle est la syntaxe est la bonne façon de déclarer une structure C?
J'ai vu C structs déclaré plusieurs manières différentes en avant. Pourquoi est-ce et que, si quoi que ce soit, ne faire de différent?
Par exemple:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}
- Ce n'est pas la réponse à votre question pour le C, mais je crois qu'ils sont tous corrects pour le C++, mais le premier est préféré. Cela peut aussi avoir changé entre les différentes versions de C, mais je vais laisser quelqu'un d'autre en parler, puisque je ne suis pas spécialiste de l'histoire de C/C++.
- C++ est différente: lorsque vous écrivez
struct Foo { };
ouclass Foo { };
là, vous obtenezFoo
gratuitement sanstypedef
. - Ils seront tous encore du travail, mais, même si l'on peut faire des choses légèrement différentes (comme polluer votre espace de noms w/ extra tags).
- Pas exactement.
class X
vous permet de déclarerX x;
, maisX
est toujours dans leclass
/struct
tag de noms, ce qui permet aux gens d'essayer des choses désagréables commeclass singleton { ... } singleton;
- Notez que l'utilisation des principaux traits de soulignement dans votre struct noms de balise est presque certainement incorrecte. Il peut casser des choses et ne sert aucun but. Ne pas le faire.
Vous devez vous connecter pour publier un commentaire.
Bien, la différence la plus évidente est démontré dans votre
main
:La première déclaration des nations unies
typedef
edstruct
et les besoins de lastruct
mot-clé à utiliser. La seconde est d'untypedef
ed anonymestruct
, et donc nous utilisons letypedef
nom. La troisième combine à la fois la première et la deuxième: votre exemple utilisebaz
(qui est bien court), mais il pourrait tout aussi bien utiliserstruct _baz
pour le même effet.Mise à jour: larsmans réponse mentionne un cas plus courant où vous devez utiliser au moins
struct x { }
pour faire une liste chaînée. Le deuxième cas ne serait pas possible ici (sauf si vous renoncez à la santé mentale et l'utilisation d'unvoid *
au lieu de cela) parce que lestruct
est anonyme, et letypedef
n'arrive pas jusqu'à ce que lestruct
est défini, vous donnant pas moyen d'en faire un (de type sécurisé) pointeur vers lestruct
type lui-même. La première version fonctionne très bien pour cette utilisation, mais le troisième est généralement privilégiée dans mon expérience. Lui donner quelques rep pour que.Plus subtile différence est dans l'espace de noms de placement. En C,
struct
balises sont placées dans un autre espace de noms à partir d'autres noms, maistypedef
les noms ne sont pas. Donc la suite est juridique:Mais la suite ne l'est pas, car il serait ambigu que le nom
test
est:typedef
fait le nom plus court (toujours un plus), mais il le met dans le même espace de noms que vos variables et de fonctions. Généralement ce n'est pas un problème, mais il y a une différence subtile au-delà de la simple raccourcissement.typedef struct { ... } Foo
C'est en grande partie une question de préférence personnelle. J'aime donner de nouveaux types un nom commençant par une lettre majuscule et d'omettre le
struct
, donc j'ai l'habitude d'écrire destypedef struct { ... } Foo
. Cela signifie que je ne puis écrirestruct Foo
.L'exception est lorsqu'un
struct
contient un pointeur vers son propre type, par exempleDans ce cas, vous devez également déclarer l'
struct Node
type, depuis latypedef
n'est pas étendue à l'intérieur de lastruct
définition. Notez que les deux noms peuvent être les mêmes (je ne suis pas sûr de l'endroit où le trait de soulignement convention est née, mais je suppose que les anciens compilateurs C ne pouvais pas gérertypedef struct X X;
).Toutes vos utilisations sont syntaxiquement correctes. Je préfère l'utilisation suivante
Observer que cela permet facilement d'utiliser le
typedef
déjà à l'intérieur de la déclaration de lastruct
lui-même, et que, même pourstruct
qui référencent mutuellement.typedef struct foo foo;
dans vos en-têtes et ne fournissent pas une définition de lastruct foo
, le code de l'utilisateur disposera d'un pointeur opaque (c'est à dire qu'ils peuvent passerfoo *
les pointeurs et les recevoir à partir des fonctions de la bibliothèque, mais ne peut pas accéder à l'intérieur des membres.) C'est bon pour l'encapsulation de données et d'un idiome commun: la normeFILE *
type est une instance de cette.La confusion vient à propos, car certains de ces déclarations sont en fait de déclarer jusqu'à trois C constructions. Vous devez garder à l'esprit la différence entre:
1. Une définition de type de déclaration,
2. Une structure de définition et de
3. Une struct déclaration.
Ils sont tous très différents C constructions. Ils font tous des choses différentes, mais vous pouvez les combiner en un composé de construire, si vous le souhaitez.
Regardons chaque déclaration à son tour.
Nous voici à l'aide de la plupart de base de la structure de la définition de la syntaxe. Nous sommes à la définition de foo comme un C type, qui peut ensuite être utilisé pour déclarer des variables de ce type à l'aide de la syntaxe suivante:
//====================================================
Cette déclaration est un peu comme la syntaxe précédente en ce qu'il déclare un type C, mais il utilise la définition de type de syntaxe. Nous allons le décomposer en ses composants à l'aide de la précédente déclaration de base.
Maintenant, il suffit de remplacer le "foo" avec la syntaxe précédente et le tour est joué!
La syntaxe ci-dessus est équivalente à la séquence suivante de déclarations.