2010-12-08 8 views
5

Dans ma classe récente des systèmes d'exploitation, nous avons un tas d'objets définis comme tels:struct x vs x_t en C

typedef struct someobj { 
    ... stuff ... 
} someobj_t; 

Je sais ce que cela fait très bien.

La question est que, parfois, dans le code de support donné, les structures étaient appelées struct someobj *some, et parfois someobj_t *some. Y a-t-il une raison réelle/utile de se référer aux structures de ces deux manières différentes, ou est-ce simplement une différence stylistique?

+4

Vous manquez un 'typedef'? –

+3

Etes-vous sûr d'avoir bien compris la question? 'someobj_t' est un objet, pas un type, vous pourriez avoir omis un seul' typedef' dans votre code. – Kos

+1

la notation '_t', en supposant que vous voulez dire un typedef, si seulement une convention pour distinguer' struct someobj' et 'someobj' (en supposant que c'était le nom typedef'd) - c'est parce que C a deux" namespaces "différents pour ceux-ci (struct et typedef), et vraisemblablement cette convention aide à ajouter de la sémantique au code. –

Répondre

5

En supposant que nous demandons sur le code suivant (il n'y a pas typedef dans la question que je vous écris, mais je suppose qu'il était censé être là):

typedef struct someobj { 
    // content 
} someobj_t; 

En fait habituellement il suffirait d'omettre le nom someobj et d'utiliser someobj_t de manière cohérente. Cependant, il y a cette situation quand vous voulez la struct de se référer à lui-même:

typedef struct someobj { 
    struct someobj* next; 
    // cannot say someobj_t* yet - typedef not complete 
} someobj_t; 

// and from now on, both struct someobj and`someobj_t are equivalent 
1

Je pense que vous voulez dire

typedef struct someobj { 
... stuff ... 
} someobj_t; 

Cela vous permet d'utiliser someobj_ t comme un type au lieu de struct someobj. Les deux notations sont équivalentes.

2

Les auteurs ne peuvent pas savoir que vous pouvez (ou ne préfèrent pas) omettez le someobj. Si vous voulez qu'une seule façon de se référer au type, vous pouvez écrire:

typedef struct { 
    ... 
} someobj_t; 

Comme Kos mentionne dans une autre réponse, cela est bien aussi longtemps que la structure n'a pas besoin de se référer à lui-même (par exemple dans une liste chaînée). Pour un maximum de confusion, vous pouvez toujours faire:

typedef struct someobj_t { 
    ... 
} someobj_t; 
2

En supposant que vous vouliez dire:

typedef struct someobj 
{ 
    /* ... */ 
} someobj_t; 

la différence en général est juste stylistique; certaines personnes préfèrent s'en tenir au style "ancien C" pour les structures (où vous devez mettre le mot-clé struct à chaque fois que vous faites référence à ce type), d'autres aiment la façon plus synthétique d'utiliser someobj_t.

Beaucoup de gens qui utilisent le symbole défini par le typedef le trouvent plus naturel car souvent ils viennent d'autres langages (par exemple C++, C#, ...) où il n'y a pas besoin de la chose struct. Dans de nombreux cas, ils omettent même le nom struct de la déclaration et laissent simplement le nom typedef.

L'utilisation de ces deux symboles est en général équivalente, mais il y a quelques mises en garde; tout d'abord, avant la fin de la typedef la version _t n'existe pas, donc vous ne pouvez pas déclarer des pointeurs à la structure à l'intérieur de lui-même en utilisant le nom _t.

Ensuite, le typedef "n'existe" que pendant la compilation; Cela signifie que le compilateur et le débogueur se référeront à votre symbole avec le nom non typedef ed.Si vous utilisez un typedef sans un nom de structure "réel", lorsque vous devez rechercher des erreurs avec certains compilateurs/débogueurs, vous pouvez devenir fou parce que vous ne pouvez pas vous référer à un nom de structure "réel", puisque typedef structures sans nom réel sont en fait des structures anonymes.

Cela peut devenir particulièrement problématique si vous devez exporter votre structure avec MIDL et des choses comme ça; voir this post par Raymond Chen pour plus de détails. Enfin, vous pouvez faire des déclarations directes simplement avec le nom de la structure réelle; et si vous n'avez pas de nom de structure (mais seulement le typedef), vous ne pouvez pas faire de déclarations anticipées.

+0

Huh? Depuis quand l'éditeur de liens connaît-il les noms de types? –

+0

@R .: vous avez raison, je pense que je l'ai écrit parce que je suis habitué aux erreurs de linker en C++, où le linker se réfère au * type * de la classe à laquelle appartient la méthode défectueuse (même si ces types sont juste le résultat de démêler les noms de méthodes). –

6

Alors qu'il est à vous si vous utilisez un typedef ou le nom de struct, il y a une très bonne raison de ne pas utiliser typedef noms se terminant par _t. Tous ces noms sont réservés par POSIX pour une utilisation par l'implémentation, et peuvent faire référence à des types spécifiques à l'implémentation ou peuvent être standardisés dans les futures versions de POSIX. Malheureusement, de nombreux auteurs de bibliothèques ignorent cela.

Personnellement, je préfère ne pas utiliser typedef pour les structures, mais si vous choisissez de l'utiliser, évitez au moins l'espace de noms réservé.

+0

http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html (juste en fournissant un lien vers la source canonique) –