web-dev-qa-db-fra.com

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

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

int_t anInt;

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

212
Kevin Griffin

Comme l'a souligné Douglas Mayle, il s'agit essentiellement d'un nom de type. Par conséquent, il serait mal avisé de terminer les noms de variable ou de fonction par '_t', car cela pourrait créer une certaine confusion. En plus de size_t, la norme C89 définit wchar_t, off_t, ptrdiff_t et probablement quelques autres que j'ai oubliés. La norme C99 définit un grand nombre de types supplémentaires, tels que uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, etc. Ces nouveaux types sont formellement définis dans <stdint.h> mais vous utiliserez le plus souvent <inttypes.h> qui (exceptionnellement pour les en-têtes C standard) inclut <stdint.h>. Il (<inttypes.h>) définit également les macros à utiliser avec les fonctions printf() et scanf().

Comme Matt Curtis l'a noté, le suffixe n'a pas d'importance pour le compilateur; c'est une convention à orientation 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 la mise en oeuvre. 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 interpellés par des systèmes définissant des types avec le même nom que nous définissons.

171
Jonathan Leffler

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;
39
mmacaulay

Le _t enveloppe généralement une définition de type opaque.

GCC ajoute simplement les noms se terminant par _t à l'espace de noms réservé que vous ne pouvez pas utiliser, afin d'éviter tout conflit avec les versions futures 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 le standard POSIX (1003.1, Rationale (Informatif)):

B.2.12 Types de données

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

En résumé, la norme indique qu'il y a de bonnes chances d'étendre la liste des types de normes, aussi limite-t-elle l'espace de nom _t à son propre usage.

Par exemple, votre programme correspond POSIX 1003.1 Problèmes 6 et vous avez défini un type foo_t. Les problèmes POSIX 1003.1 7 sont finalement publiés avec un nouveau type défini foo_t. Votre programme ne correspond pas à la nouvelle version, ce qui pourrait poser problème. Restreindre l'utilisation de _t empêche de refactoriser le code. Ainsi, si vous visez une conformité POSIX, vous devez absolument éviter le _t comme le stipule 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 style de codage Linux (chapitre 5) . Pourquoi ne pas utiliser typedef? J'espère que cette aide!

35
Benoit

C'est une convention de dénomination standard pour les types de données, généralement définie par typedefs. Une grande partie du code C traitant des registres matériels utilise 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 sont dans un fichier d'en-tête standard (stdint.h) et se terminent par _t.

16
mkClark

Le _t n'a intrinsèquement aucune signification particulière. Mais il est devenu courant d’ajouter le suffixe _t à typedef.

Vous connaissez peut-être mieux les pratiques courantes du C en matière de nommage des variables ... Ceci est similaire à la façon habituelle de coller un pointeur devant un pointeur et d'utiliser un trait de soulignement devant des variables globales (c'est un peu moins courant) , et d'utiliser les noms de variable i, j et k pour les variables de boucle temporaires.

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

int_t n'est pas très bon, car la définition de int varie d'une plate-forme à l'autre. Alors à qui int vous conformez-vous? (Bien que, de nos jours, la plupart des projets de développement centrés sur le PC le traitent en 32 bits, la plupart des éléments destinés au développement autre que sur PC traitent toujours les interfaces en 16 bits). 

11
Toybuilder

Cela signifie le type. size_t est le type de taille.

9
Douglas Mayle

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

9
Matt Curtis

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 (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 conflits avec les types existants dans le système d’exploitation que vous intégrez dans votre code. Pour cela, un préfixe unique (autant que possible) est généralement ajouté.

Exemple:

typedef unsigned long dc_uint32_t;
8
Ilya

Si vous utilisez du code d'interface matérielle, l'auteur du code que vous consultez peut avoir défini int_t comme étant un entier de taille spécifique. Le standard C n'attribue pas de taille spécifique au type int (cela dépend éventuellement de votre compilateur et de la plate-forme cible), et l'utilisation d'un type int_t 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 expliquer pourquoi vous avez tout d'abord remarqué la convention.

6
Greg Hewgill

Par exemple, dans 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.

0
Jayhello