2010-03-01 1 views
3

Parfois je vois code comme ceci (je l'espère, je me souviens bien):Pourquoi le tagName d'une structure diffère-t-il souvent du nom du typedef?

typedef struct st { 
    int a; char b; 
} *stp; 

Alors que le schéma habituel que je connais bien, est:

typedef struct st { 
    int a; char b; 
} st; 

Alors, quel est l'avantage dans le premier code Exemple?

+0

L'astérisque est-il vraiment un astérisque dans le code source? Ou juste un joker? – kennytm

+0

Prenez-le en tant que wildcard s'il vous plaît. Pour une raison quelconque, je me souviens d'un astérisque, mais cela ne compile pas. – Dor

+0

Voulez-vous dire 'struct _st' au lieu de' struct * st'? – Artelius

Répondre

6

Vous voulez dire sans doute ceci:

typedef struct ST { 
    /* fields omitted */ 
} *STP; 

L'astérisque est à la fin de l'instruction. Cela signifie simplement "définir le type STP comme un pointeur vers une structure de ce type". La balise struct (ST) n'est pas nécessaire, elle n'est utile que si vous voulez pouvoir vous référer au type struct par lui-même, plus tard.

Vous pouvez aussi avoir les deux, comme ceci:

typedef struct { 
    /* fields omitted */ 
} ST, *STP; 

Cela permettrait d'utiliser ST pour désigner le type struct lui-même, et STP pour les pointeurs de ST. Personnellement, je trouve très mauvais d'inclure l'astérisque dans typedefs, puisqu'il essaye d'encoder quelque chose (le fait que le type est un pointeur) dans le nom du type, alors que C fournit déjà son propre mécanisme (l'astérisque) pour le montrer. Cela le rend très confus et rompt la symétrie de l'astérisque, qui apparaît à la fois dans la déclaration et l'utilisation de pointeurs.

+2

'typedef' ing' * 'est utile pour les types opaques, qui pourraient être implémentés comme des pointeurs, mais qui auraient aussi bien pu être implémentés comme des identifiants numériques; si cela est fait judicieusement, les informations qui se cachent dans 'typedef' sont une bonne chose. – Christoph

1

J'espère que le premier code dirait une erreur du compilateur,

+0

En effet il y avait une erreur. Voir les commentaires à ma question. – Dor

2

Je pense que vous parlez:

 
typedef struct{ 
    int a; 
    char b; 
} object, *objectPointer;

Cela signifie que (nouveau) de type objectPointer est un pointeur vers struct (objet) défini ci-dessus. Il est facile de déclarer des pointeurs sur l'objet struct de cette façon. Par exemple,

objectPointer A = (objectPointer)malloc(sizeof(object)); 
A->a = 2; 

Maintenant, A est un pointeur sur struct objet et vous pouvez accéder à ses variables comme décrit ci-dessus.

Dans le cas, objectPointer n'a pas été défini,

 
struct object *A = (struct object *)malloc(sizeof(object)); 
A->a = 2; 
Donc, je suppose que objectPointer est plus intuitive et facile à utiliser.

+0

Non, cela signifie que quelque chose de type' object' est un pointeur vers 'struct _object'. – Artelius

+0

@Artelius: oh oui. Je devrais clairement écrire le type. Merci. –

+0

+1. Dans le premier code: Un point-virgule est-il omis à la fin de la structure? (ligne 4) – Dor

3

C'est une habitude qui découle du moment où les noms de typedef et les struct-tagnames étaient dans le même espace de noms. Voir http://blogs.msdn.com/oldnewthing/archive/2008/03/26/8336829.aspx

+0

Avez-vous une autre référence indiquant qu'il y avait un tel moment? Je vais essayer de creuser dans la page d'accueil DMR et d'autres documents anciens que j'ai. confirmer. Je ne m'en souviens pas. (Ce dont je me souviens, c'est que l'espace de noms des membres était unique pour toutes les structures et unions, qui explique les préfixes dans les noms de membres des structures Unix). – AProgrammer

+0

Non, mais je considère que OldNewThing est assez fiable. – Artelius

+0

Merci, apprécié la lecture du post référencé. +1 – Dor

0

Je ne vois aucune bonne raison pour que le nom de typedef soit différent du nom de balise.

Maintenant, la raison pour laquelle le nom de l'étiquette doit être typedefed si vous ne voulez pas utiliser

struct tag v; 

mais

tag v; 

est probablement historique.Pour autant que je me souvienne, C avait typedef mais je ne sais pas si c'était vrai quand struct ont été introduits (la manipulation de typedef est une nuisance dans la grammaire C). Dans l'ancien code, je l'ai vu, en utilisant typedef pour struct ne se fait pas, et il y a des choses comme unix

struct stat; 
int stat(const char*, struct stat*); 

qui romprait avec un typedef automatique. Une de celles-ci est introduite, changer est assez difficile (oui, C++ a un typedef automatique mais C++ a un libellé spécial pour gérer ce cas de surcharge et ce serait encore une autre complication).

Questions connexes