Qu'est-ce que uint_fast32_t et pourquoi devrait-il être utilisé à la place des int réguliers et uint32_t?

110

Donc, la raison de typedef: ed les types de données primitifs est d'abstraire la représentation de bas niveau et de la rendre plus facile à comprendre ( uint64_tau lieu du long longtype, qui est de 8 octets).

Cependant, il y a uint_fast32_tqui a le même typedefque uint32_t. L'utilisation de la version "rapide" rendra-t-elle le programme plus rapide?

Amumu
la source
long long n'est peut-être pas 8 octets, il est possible d'avoir un long long avec 1 octet (dans le cas où CHAR_BIT vaut au moins 64) ou avec 3738383 octets. aussi uint64_t peut être 1,2,4 ou 8 octets, CHAR_BIT doit être 64, 3, 16 ou 8 pour cela.
12431234123412341234123

Réponses:

135
  • intpeut être aussi petit que 16 bits sur certaines plates-formes. Cela peut ne pas être suffisant pour votre application.
  • uint32_tn'est pas garanti d'exister. C'est une option typedefque l'implémentation doit fournir ssi elle a un type entier non signé d'exactement 32 bits. Certains ont des octets de 9 bits par exemple, ils n'ont donc pas de fichier uint32_t.
  • uint_fast32_tindique clairement votre intention: c'est un type d' au moins 32 bits qui est le meilleur du point de vue des performances. uint_fast32_tpeut être en fait de 64 bits de long. Cela dépend de la mise en œuvre.

... il y a uint_fast32_tqui a le même typedef que uint32_t...

Ce que vous regardez n'est pas la norme. C'est une implémentation particulière (BlackBerry). Vous ne pouvez donc pas en déduire que uint_fast32_tc'est toujours la même chose uint32_t.

Voir également:

Yakov Galka
la source
36
Bonne réponse. Par souci d'exhaustivité, on pourrait peut-être aussi souligner la différence uint_least32_t, ce qui revient au même que uint_fast32_tsauf que cela favorise un plus petit magasin plutôt que la vitesse.
Damon
2
Pourquoi l'entier le plus rapide d'une largeur d'au moins 32 bits serait-il supérieur à 32 bits? J'ai toujours pensé que s'il y avait moins de bits, il y aurait moins de bits sur lesquels le processeur devait travailler, donc plus rapidement. Qu'est-ce que j'oublie ici?
Shane Hsu
12
@ShaneHsu: disons qu'un processeur 64 bits aura un été 64 bits, qui additionne les nombres 64 bits en un cycle. Peu importe si tout ce que vous voulez faire est de travailler sur des nombres 32 bits, cela ne va pas être plus rapide qu'un cycle. Maintenant, bien que ce ne soit pas le cas sur x86 / amd64, les entiers 32 bits peuvent même ne pas être adressables. Dans un tel cas, travailler dessus nécessite des opérations supplémentaires pour extraire les 32 bits à partir, par exemple, d'unités alignées sur 64 bits. Voir également la question liée. La norme C ++ est écrite pour qu'elle puisse fonctionner sur une machine qui a des mots de 37 bits ... donc pas de type 32 bits du tout.
Yakov Galka
42

La différence réside dans leur exactitude et leur disponibilité.

Le doc ici dit:

type entier non signé avec une largeur d' exactement 8, 16, 32 et 64 bits respectivement ( fourni uniquement si l'implémentation prend directement en charge le type ):

uint8_t
uint16_t
uint32_t
uint64_t

Et

type entier non signé le plus rapide avec une largeur d' au moins 8, 16, 32 et 64 bits respectivement

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

La différence est donc assez claire: uint32_tc'est un type qui a exactement des 32 bits, et une implémentation ne devrait le fournir que si elle a un type avec exactement 32 bits, puis elle peut taper ce type comme uint32_t. Cela signifie, uint32_tpeut ou peut ne pas être disponible .

D'autre part, uint_fast32_test un type qui a au moins 32 bits, ce qui signifie également, si une implémentation peut typedef uint32_tcomme uint_fast32_t si elle fournit uint32_t. S'il ne fournit pas uint32_t, alors uint_fast32_tpourrait être un typedef de n'importe quel type qui a au moins des 32bits.

Nawaz
la source
3
Mais quelle est la raison qui rend par exemple uint_fast32_t plus rapide que uint32_t? Pourquoi c'est plus rapide?
Destructor
2
@PravasiMeet: tous les entiers ne sont pas accessibles de la même manière. Certains sont plus faciles d'accès que d'autres. Plus facile signifie moins de calcul, plus direct, ce qui se traduit par un accès plus rapide. C'est maintenant uint32_texactement 32 bits sur tous les systèmes (s'il existe), ce qui n'est peut-être pas plus rapide que celui qui a, disons, 64 bits. uint_fast32_td'autre part au moins 32 bits, pourrait même être 64 bits.
Nawaz
10
@Destructor: Sur certains processeurs, si une variable est stockée dans un registre qui est plus long, le compilateur devra peut-être ajouter du code supplémentaire pour supprimer les bits supplémentaires. Par exemple, si uint16_t x;est stocké dans un registre 32 bits sur l'ARM7-TDMI, le code x++;peut devoir être évalué comme x=((x+1)<<16)>>16);. Sur les compilateurs pour cette plate-forme, uint_fast16_tserait probablement défini comme synonyme de uint32_tpour éviter cela.
supercat du
pourquoi [u]int_(fast|least)N_tne sont pas également facultatifs? Toutes les architectures ne sont certainement pas requises par la norme pour prendre en charge les types primitifs d'au moins 64 bits? Pourtant, le libellé pour stdint.himplique qu'ils doivent. Il me semble étrange que nous appliquions cela depuis 1999, quelques années avant que l'informatique 64 bits ne devienne courante - sans parler du retard (dans de nombreux cas encore actuel) des architectures embarquées. Cela me semble être un gros oubli.
underscore_d
1
@underscore_d: Il n'y a aucune raison particulière, par exemple, que la norme ne puisse pas être applicable à une implémentation PIC12 avec 16 octets de RAM de données et un espace pour 256 instructions. Une telle implémentation aurait besoin de rejeter beaucoup de programmes, mais cela ne devrait pas l'empêcher de se comporter de manière définie pour les programmes dont elle pourrait satisfaire les besoins.
supercat
4

Lorsque vous êtes #include inttypes.hdans votre programme, vous avez accès à un tas de façons différentes de représenter des entiers.

Le type uint_fast * _t définit simplement le type le plus rapide pour représenter un nombre donné de bits.

Pensez-y de cette façon: vous définissez une variable de type shortet vous l'utilisez plusieurs fois dans le programme, ce qui est totalement valide. Cependant, le système sur lequel vous travaillez peut fonctionner plus rapidement avec des valeurs de type int. En définissant une variable comme type uint_fast*t, l'ordinateur choisit simplement la représentation la plus efficace avec laquelle il peut travailler.

S'il n'y a pas de différence entre ces représentations, alors le système choisit celle qu'il veut et l'utilise de manière cohérente.

Harley Sugarman
la source
9
Pourquoi inttypes.h et pas stdint.h? Il semble que inttypes.h ne contienne que divers fluff légèrement utiles, plus une inclusion de stdint.h?
Lundin
@underscore_d Je connais la différence. Mais qui utilise stdio.h dans les programmes professionnels, quel que soit le domaine d'application?
Lundin le
@Lundin Je n'ai aucune idée de qui ils sont, ni s'ils existent! J'ai juste pensé qu'il pourrait être utile de fournir un lien expliquant ce qu'est ce "fluff légèrement utile" ;-) Cela aidera peut-être les gens à réaliser que vous avez raison et qu'ils n'en ont pas besoin.
underscore_d
-1

Notez que la version rapide peut être supérieure à 32 bits. Alors que le fast int s'intégrera bien dans un registre et sera aligné, etc., mais il utilisera plus de mémoire. Si vous avez de grands tableaux de ceux-ci, votre programme sera plus lent en raison de plus de hits de mémoire cache et de bande passante.

Je ne pense pas que le CPUS moderne bénéficiera de fast_int32, car en général, l'extension du signe de 32 à 64 bits peut se produire pendant l'instruction de chargement et l'idée qu'il existe un format entier «natif» plus rapide est démodée.

Gil Colgate
la source