Question

Je rencontrais une lecture de code

typedef enum eEnum { c1, c2 } tagEnum;

typedef struct { int i; double d; } tagMyStruct;

J'ai entendu des rumeurs selon lesquelles ces constructions datent de C. En C ++, vous pouvez facilement écrire

enum eEnum { c1, c2 };
struct MyStruct { int i; double d; };

Est-ce vrai? Quand avez-vous besoin de la première variante?

Était-ce utile?

La solution

Tout d'abord, les deux déclarations sont légales dans les deux C et C ++. Cependant, en C, ils ont une sémantique légèrement différente. (En particulier, la façon dont vous faites référence à la struct varie plus tard).

Le concept clé est de comprendre que, dans C, struct existent dans un espace de noms séparé. Tous les types intégrés, ainsi que typedefs existent dans l'espace de noms « par défaut ». Autrement dit, lorsque je tape int, le compilateur ne vérifie que cet espace de noms « par défaut ». Si je tape « tagMyStruct » comme dans votre exemple, le compilateur vérifie également que celui-ci espace de noms. Mais selon quel type de déclaration que vous utilisez, la struct ne peut pas exister dans cet espace de noms.

Structs sont différents, et existent dans un espace de noms séparé. Donc, si je fais la déclaration suivante:

struct mystruct {};

Je pas se référer simplement comme mystruct. Au lieu de cela, je dois préciser que je veux le mystruct qui existe dans l'espace de noms struct:

void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter

Ce qui devient un peu bavard et maladroit à long terme. Au lieu de cela, vous pouvez typedef dans l'espace de noms par défaut:

typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace

et maintenant, ma fonction peut être déclarée de façon directe:

void foo(mystruct bar);

Ainsi, votre premier exemple fusionne simplement ces deux étapes ensemble: Déclarez une struct, et mettre un alias dans l'espace de noms régulier. Et bien sûr, puisque nous typedeffing toute façon, on n'a pas besoin du nom « d'origine », afin que nous puissions rendre anonyme le struct. Ainsi, après votre déclaration

typedef struct { int i; double d; } tagMyStruct;

nous avons un struct sans nom, qui a été typedef à « tagMyStruct » dans l'espace de noms par défaut.

Voilà comment C la traite. Les deux types de déclarations sont valables, mais on ne crée pas l'alias dans l'espace de noms « par défaut », donc vous devez utiliser le mot-clé struct chaque fois que vous faites référence au type.

En C ++, l'espace de noms struct séparé n'existe pas, donc ils veulent dire la même chose. . (Mais la version plus courte est préférée)

Modifier Juste pour être clair, non, C n'a pas namespaces. Pas dans le sens habituel. C place simplement les identificateurs dans l'un des deux espaces de noms prédéfinis. Les noms des struct (et énumérations, je me souviens bien) sont placés dans un, et tous les autres identifiants dans un autre. Techniquement, ce sont des espaces de noms parce qu'ils sont « conteneurs » séparés dans lesquels sont placés les noms pour éviter les conflits, mais ils ne sont certainement pas dans le C namespaces ++ / C # sens.

Autres conseils

En C, si vous deviez écrire

struct MyStruct { int i; double d; };

chaque fois que vous voulez faire référence à ce type, vous auriez à préciser que vous parlez d'un struct:

struct MyStruct instanceOfMyStruct;
struct MyStruct *ptrToMyStruct;

Avec la version typedef:

typedef struct { int i; double d; } tagMyStruct;

il suffit d'écrire:

tagMyStruct instanceOfMyStruct;
tagMyStruct *ptrToMyStruct;

L'autre grand avantage avec la version typedef est que vous pouvez vous référer à la struct de la même manière dans les deux C et C ++, alors que dans la deuxième version, ils sont refered à différemment en C que dans C ++.

Il est juste un raccourci.

Dans le second cas, de déclarer la struct que vous souhaitez le faire avec:

struct MyStruct a;

Dans la première variante, vous feriez donc avec:

tagMyStruct a;

La seconde variante existe aussi en C.

Vous utilisez la première variante chaque fois que vous voulez nommer votre type, par exemple:.

tagEnum myFunc(tagMyStruct * myArg);

Le premier peut être gênant en C ++, comme vous ne pouvez pas déclarer avant dans un fichier d'en-tête.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top