Que représente un type suivi de _t (trait de soulignement-t)?

261

Cela semble être une question simple, mais je ne la trouve pas avec la recherche Stack Overflow ou Google. Que signifie un type suivi d'une _tmoyenne? Tel que

int_t anInt;

Je le vois beaucoup dans le code C destiné à traiter étroitement avec le matériel - je ne peux m'empêcher de penser qu'ils sont liés.

Kevin Griffin
la source
3
Où est int_tdéfini? Si c'est toujours défini comme int, ce n'est pas utile; c'est beaucoup plus clair à utiliser intdirectement. Si ce n'est pas toujours défini comme int(disons, si cela pourrait être long intou short int), alors c'est un nom mal choisi et déroutant.
Keith Thompson

Réponses:

213

Comme l'a noté Douglas Mayle, il désigne essentiellement un nom de type. Par conséquent, il serait mal avisé de terminer les noms de variables ou de fonctions par ' _t' car cela pourrait créer une certaine confusion. Ainsi que size_t, la norme C89 définit wchar_t, off_t, ptrdiff_tet probablement d'autres , je l' ai oublié. La norme définit C99 beaucoup de types supplémentaires, tels que uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, et ainsi de suite. Ces nouveaux types sont formellement définis dans <stdint.h>mais le plus souvent, vous les utiliserez <inttypes.h>(ce qui est inhabituel pour les en-têtes C standard) <stdint.h>. Il ( <inttypes.h>) définit également les macros à utiliser avec printf()et scanf().

Comme Matt Curtis l'a noté, il n'y a aucune signification pour le compilateur dans le suffixe; c'est une convention à vocation humaine.

Cependant, vous devez également noter que POSIX définit un grand nombre de noms de types supplémentaires se terminant par ' _t' et réserve le suffixe pour l'implémentation. Cela signifie que si vous travaillez sur des systèmes liés à POSIX, il est déconseillé de définir vos propres noms de type avec la convention. Le système sur lequel je travaille le fait (depuis plus de 20 ans); nous sommes régulièrement déclenchés par des systèmes définissant des types avec le même nom que nous définissons.

Jonathan Leffler
la source
4
il semble raisonnable que le système d'exploitation et les bibliothèques d'exécution communes définissent des types avec des noms génériques; mais les types de votre entreprise ne devraient-ils pas également être précédés d'un préfixe ou autre?
Toybuilder
17
J'utilise _type au lieu de _t sur mes typedefs précisément pour éviter cela.
CesarB
4
@Jonathan Leffler - Quelle convention de dénomination utiliseriez-vous pour les types définis par l'utilisateur?
J. Andrew Laughlin
15
@Andrew: si vous avez une abréviation pratique à utiliser comme préfixe, vous pouvez utiliser abbr_xxxxx_tdes noms de type en toute sécurité . Sans un tel préfixe, vous pouvez vous faire attraper à tout moment. Généralement, les _ttypes standardisés utilisent tous les minuscules ( FILEet DIRsont deux exceptions, deux fois - tous les majuscules et non _t), vous pouvez donc utiliser CamelCase_tavec une sécurité modérée, avec ou sans les majuscules. Le système sur lequel je travaille principalement a tendance à vivre dangereusement et à utiliser de _ttoute façon, mais il nous a parfois mordu. J'ai tendance à utiliser CamelCasesans suffixe pour mon propre travail; mes fonctions sont généralement toutes en minuscules.
Jonathan Leffler
5
@JonathanLeffler, j'ai commencé à utiliser cette convention, CamelCase pour les types, lower_case pour les fonctions. J'ai cherché cette question en espérant que je n'étais pas le seul. Merci pour la validation!
Austin Mullins
50

C'est une convention utilisée pour nommer les types de données, par exemple avec typedef:


typedef struct {
  char* model;
  int year;
...
} car_t;

mmacaulay
la source
43

L' _tencapsule généralement une définition de type opaque.

GCC ajoute simplement des noms se terminant par _tà l'espace de noms réservé que vous ne pouvez pas utiliser, pour éviter les conflits avec les futures versions de Standard C et POSIX (manuel de la bibliothèque GNU C) . Après quelques recherches, j'ai finalement trouvé la référence correcte dans la norme POSIX (1003.1, Justification (informative)):

B.2.12 Types de données

L'exigence que les types supplémentaires définis dans cette section se terminent par '' _t '' a été provoquée par le problème de la pollution de l'espace des noms. Il est difficile de définir un type (où ce type n'est pas celui défini par IEEE Std 1003.1-2001) dans un fichier d'en-tête et de l'utiliser dans un autre sans ajouter de symboles à l'espace de nom du programme. Pour permettre aux implémenteurs de fournir leurs propres types, toutes les applications conformes doivent éviter les symboles se terminant par '' _t '', ce qui permet à l'implémenteur de fournir des types supplémentaires. Étant donné qu'une utilisation importante des types se trouve dans la définition des membres de structure, qui peuvent (et dans de nombreux cas doivent) être ajoutés aux structures définies dans IEEE Std 1003.1-2001, le besoin de types supplémentaires est convaincant.

En un mot, la norme dit qu'il y a de bonnes chances d'étendre la liste des types de normes, par conséquent, la norme restreint l' _tespace de noms à son propre usage.

Par exemple, votre programme correspond à POSIX 1003.1 Issues 6 et vous avez défini un type foo_t. POSIX 1003.1 Issues 7 est finalement publié avec un nouveau type défini foo_t. Votre programme ne correspond pas à la nouvelle version, ce qui pourrait être un problème. Restreindre l' _tutilisation empêche de refactoriser le code. Ainsi, si vous visez une conformité POSIX, vous devez absolument éviter le _tcomme l'indique la norme.

Note latérale: personnellement, j'essaie de m'en tenir à POSIX car je pense que cela donne de bonnes bases pour une programmation propre. De plus, j'aime beaucoup les directives Linux Coding Style (chapitre 5) . Il y a de bonnes raisons de ne pas utiliser typedef. J'espère que cette aide!

Benoit
la source
18

Il s'agit d'une convention de dénomination standard pour les types de données, généralement définie par des typedefs. De nombreux codes C qui traitent des registres matériels utilisent des noms standard définis par C99 pour les types de données de taille fixe signés et non signés. Par convention, ces noms se trouvent dans un fichier d'en-tête standard (stdint.h) et se terminent par _t.

mkClark
la source
11

C'est juste une convention qui signifie "type". Cela ne signifie rien de spécial pour le compilateur.

Matt Curtis
la source
11

Le _tn'a pas par nature de signification particulière. Mais il est devenu d'usage courant d'ajouter le _tsuffixe aux typedef.

Vous connaissez peut-être mieux les pratiques courantes en C pour la dénomination des variables ... Cela ressemble à la façon dont il est courant de coller ap à l'avant pour un pointeur et d'utiliser un trait de soulignement devant les variables globales (c'est un peu moins courant) et d'utiliser les noms de variables i, jet kpour les variables de boucle temporaires.

Dans le code où la taille des mots et l'ordre sont importants, il est très courant d'utiliser des types définis par l'utilisateur qui sont explicites, tels que BYTE WORD(normalement 16 bits) DWORD(32 bits).

int_tn'est pas si bon, car la définition de intvarie selon les plates-formes - à qui intêtes-vous conforme? (Bien que, de nos jours, la plupart des développements centrés sur PC le traitent comme 32 bits, beaucoup de choses pour le développement non-PC traitent toujours les int comme 16 bits).

Constructeur de jouets
la source
10

Cela signifie le type. size_test le type de taille.

Douglas Mayle
la source
8

Il y avait quelques bonnes explications sur le sujet. Juste pour ajouter une autre raison de redéfinir les types:

Dans de nombreux projets intégrés, tous les types sont redéfinis pour indiquer correctement le dimensionnement donné aux types et pour améliorer la portabilité sur différentes plates-formes (c'est-à-dire les compilateurs de types de matériel).

Une autre raison sera de rendre votre code portable sur différents systèmes d'exploitation et d'éviter les collisions avec les types existants dans le système d'exploitation que vous intégrez dans votre code. Pour cela, un préfixe unique (le plus possible) est généralement ajouté.

Exemple:

typedef unsigned long dc_uint32_t;
Il y a
la source
7

Si vous avez affaire à du code d'interface matérielle, l'auteur du code que vous int_tconsultez peut avoir défini comme un entier de taille spécifique. La norme C n'attribue pas de taille spécifique au inttype (cela dépend de votre compilateur et de la plate-forme cible, potentiellement), et l'utilisation d'un int_ttype spécifique éviterait ce problème de portabilité.

Ceci est une considération particulièrement importante pour le code d'interface matérielle, ce qui peut être la raison pour laquelle vous avez remarqué pour la première fois la convention.

Greg Hewgill
la source
1
ce ne sera pas une très bonne pratique, je m'attends à ce que l'on définisse [u] int_ [32 16 8] _t pour préciser quelle est la taille que vous définissez.
Ilya
1
Vous avez tout à fait raison, "int_t" en soi dit au programmeur que c'est un type défini par l'utilisateur mais pas ce qu'il est vraiment!
Greg Hewgill,
0

Par exemple en C99, /usr/include/stdint.h:

typedef unsigned char           uint8_t;
typedef unsigned short int      uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int            uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int       uint64_t;
#else
__extension__
typedef unsigned long long int  uint64_t;
#endif

_t signifie toujours défini par typedef.

Jayhello
la source