web-dev-qa-db-fra.com

unsigned int vs. size_t

Je remarque que le code C et C++ moderne semble utiliser size_t au lieu de int/unsigned int un peu partout - des paramètres pour les fonctions de chaîne C au STL. Je suis curieux de savoir la raison de cela et les avantages que cela apporte.

473
Rob

Le type size_t est le type entier non signé qui est le résultat de l'opérateur sizeof (et de l'opérateur offsetof). Il est donc garanti qu'il est suffisamment grand pour contenir la taille du plus grand objet que votre système peut gérer (par exemple, un tableau statique de 8 Go).

Le type size_t peut être supérieur, égal ou inférieur à un unsigned int, et votre compilateur peut en déduire des hypothèses d'optimisation.

Vous pouvez trouver des informations plus précises dans la norme C99, section 7.17, dont un projet est disponible sur Internet au format pdf , ou dans la norme C11, section 7.19, également disponible au format version préliminaire pdf .

371
Remo.D

Le C classique (premier dialecte du C décrit par Brian Kernighan et Dennis Ritchie dans le langage de programmation C de Prentice-Hall, 1978) ne fournissait pas size_t. Le comité des normes C a introduit size_t pour éliminer un problème de portabilité

expliqué en détail sur embedded.com (avec un très bon exemple)

93
azeemarif

En bref, size_t n'est jamais négatif et optimise les performances, car il s'agit du type entier non signé qui est assez grand - mais pas trop grand - pour représenter la taille du plus grand objet possible sur la cible. Plate-forme.

Les tailles ne doivent jamais être négatives, et en effet size_t est un type non signé. De plus, étant donné que size_t est non signé, vous pouvez stocker des nombres environ deux fois plus grands que dans le type signé, car nous pouvons utiliser le bit de signe pour représenter la magnitude, comme tous les autres bits de l'entier non signé. Lorsque nous gagnons un bit de plus, nous multiplions la plage de nombres que nous pouvons représenter par un facteur d'environ deux.

Alors, vous vous demandez, pourquoi ne pas simplement utiliser un unsigned int? Il ne sera peut-être pas capable de contenir suffisamment de nombres. Dans une implémentation où unsigned int est 32 bits, le plus grand nombre qu'il peut représenter est 4294967295. Certains processeurs, tels que l'IP16L32, peuvent copier des objets de plus de 4294967295 octets.

Alors, vous vous demandez, pourquoi ne pas utiliser un unsigned long int? Cela impose des performances sur certaines plates-formes. La norme C exige que long occupe au moins 32 bits. Une plate-forme IP16L32 implémente chaque longueur de 32 bits sous la forme d'une paire de mots de 16 bits. Presque tous les opérateurs 32 bits de ces plates-formes requièrent deux instructions, sinon plus, car ils fonctionnent avec les 32 bits en deux morceaux de 16 bits. Par exemple, déplacer une longueur de 32 bits nécessite généralement deux instructions machine, une pour déplacer chaque bloc de 16 bits.

L'utilisation de size_t évite cette perte de performances. Selon cet article fantastique , "Type size_t est un typedef qui est un alias pour un type entier non signé, généralement unsigned int ou unsigned long, mais peut-être même unsigned long long. Chaque implémentation Standard C est supposée choisir un entier non signé suffisamment grand - mais pas plus grand que nécessaire - pour représenter la taille du plus grand objet possible sur la plate-forme cible. "

71
Rose Perrone

Le type size_t est le type renvoyé par l'opérateur sizeof. Il s'agit d'un entier non signé capable d'exprimer la taille en octets de toute plage de mémoire prise en charge sur la machine hôte. Il est (généralement) lié à ptrdiff_t en ce que ptrdiff_t est une valeur entière signée telle que sizeof (ptrdiff_t) et sizeof (size_t) sont égaux.

Lorsque vous écrivez du code C, vous devez toujours utiliser size_t pour gérer les plages de mémoire.

Le type int, quant à lui, est fondamentalement défini comme la taille de la valeur entière (signée) que la machine hôte peut utiliser pour effectuer de manière efficace l'arithmétique des entiers. Par exemple, sur de nombreux ordinateurs de type PC plus anciens, la valeur sizeof (size_t) serait de 4 (octets) mais sizeof (int) serait de 2 (octet). L'arithmétique 16 bits était plus rapide que l'arithmétique 32 bits, bien que le CPU puisse gérer un espace mémoire (logique) de 4 Gb.

Utilisez le type int uniquement lorsque vous vous souciez de l'efficacité, car sa précision réelle dépend fortement des options du compilateur et de l'architecture de la machine. En particulier, le standard C spécifie les invariants suivants: sizeof (char) <= sizeof (court) <= sizeof (int) <= sizeof (long), n'imposant aucune autre limitation à la représentation réelle de la précision disponible pour le programmeur ces types primitifs.

Remarque: Il ne s'agit PAS de la même chose que dans Java (qui spécifie en fait la précision en bits de chacun des types 'char', 'byte', 'short', 'int' et 'long').

50
Kevin S.

Le type size_t doit être suffisamment grand pour stocker la taille de tout objet possible. Unsigned int ne doit pas nécessairement satisfaire à cette condition.

Par exemple, dans les systèmes 64 bits, int et unsigned int peuvent avoir une largeur de 32 bits, mais size_t doit être suffisamment grand pour stocker des nombres supérieurs à 4G.

23
Maciej Hehl

Cet extrait du manuel glibc 0.02 peut également être utile lors de la recherche sur le sujet:

Il existe un problème potentiel avec le type size_t et les versions de GCC antérieures à la version 2.4. ANSI C requiert que size_t soit toujours un type non signé. Pour assurer la compatibilité avec les fichiers d’en-tête des systèmes existants, GCC définit size_t dans stddef.h' to be whatever type the system'ssys/types.h '. La plupart des systèmes Unix qui définissent size_t dans `sys/types.h ', définissent le type signé. Certains codes de la bibliothèque dépendent du fait que size_t est un type non signé et ne fonctionnera pas correctement s’il est signé.

Le code de la bibliothèque GNU C qui attend que size_t ne soit pas signé est correct. La définition de size_t en tant que type signé est incorrecte. Nous prévoyons que dans la version 2.4, GCC définira toujours size_t en tant que type non signé et le fixincludes' script will massage the system'ssys/types.h 'afin de ne pas entrer en conflit avec cela.

En attendant, nous contournons ce problème en indiquant explicitement à GCC d'utiliser un type non signé pour size_t lors de la compilation de la bibliothèque GNU C. `configure 'détectera automatiquement le type utilisé par GCC pour size_t, arrangez-le pour le remplacer si nécessaire.

3
Graeme Burke

Si mon compilateur est défini sur 32 bits, size_t n'est rien d'autre qu'un typedef pour unsigned int. Si mon compilateur est défini sur 64 bits, size_t n'est rien d'autre qu'un typedef pour unsigned long long.

1
Zebrafish