Question int non signé vs size_t


Je remarque que le code C et C ++ moderne semble utiliser size_t au lieu de int/unsigned int à peu près partout - des paramètres pour les fonctions de chaîne C à la STL. Je suis curieux quant à la raison de ceci et les avantages qu'il apporte.


437
2017-09-25 07:00


origine


Réponses:


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

le size_t le type peut être plus grand, égal ou plus petit qu'un unsigned int, et votre compilateur pourrait faire des suppositions à ce sujet pour l'optimisation.

Vous trouverez des informations plus précises dans la norme C99, section 7.17, dont un projet est disponible sur Internet sous pdf format, ou dans la norme C11, section 7.19, également disponible en projet de pdf.


351
2017-09-25 07:08



Classic C (le dialecte précoce de C décrit par Brian Kernighan et Dennis Ritchie dans The C Programming Language, Prentice-Hall, 1978) ne fournit pas size_t. Le comité des normes C a introduit size_t pour éliminer un problème de portabilité

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


88
2017-09-25 07:13



En bref, size_t n'est jamais négatif, et il maximise les performances car il est typedef'd être le type entier non signé qui est assez grand - mais pas trop grand - pour représenter la taille de l'objet le plus grand possible sur la plate-forme cible.

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

Donc, vous demandez, pourquoi ne pas simplement utiliser un unsigned int? Il ne sera peut-être pas capable de contenir des chiffres assez importants. Dans une mise en œuvre où unsigned int est de 32 bits, le plus grand nombre qu'il peut représenter 4294967295. Certains processeurs, tels que IP16L32, peuvent copier des objets supérieurs à 4294967295 octets.

Donc, vous demandez, pourquoi ne pas utiliser un unsigned long int? Il impose un coût de performance sur certaines plates-formes. La norme C exige qu'un long occuper au moins 32 bits. Une plate-forme IP16L32 implémente chaque longueur de 32 bits comme une paire de mots de 16 bits. Presque tous les opérateurs 32 bits sur ces plates-formes nécessitent deux instructions, sinon plus, car elles fonctionnent avec les 32 bits dans deux blocs de 16 bits. Par exemple, le déplacement d'une longueur de 32 bits nécessite généralement deux instructions - une pour déplacer chaque bloc de 16 bits.

L'utilisation de size_t évite ce bilan de performance. Selon cet article fantastique, "Type size_t est un typedef qui est un alias pour un type entier non signé, généralement non signé ou non signé, mais peut-être même non signé longtemps.Chaque implémentation de C standard est censée choisir l'entier non signé qui est assez grand - mais pas plus grand que needed - pour représenter la taille du plus grand objet possible sur la plate-forme cible. "


57
2017-11-28 03:41



Le type size_t est le type renvoyé par l'opérateur sizeof. C'est 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 (typiquement) 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 devriez toujours utilisez size_t chaque fois qu'il s'agit de plages de mémoire.

D'autre part, le type int est défini comme la taille de la valeur entière (signée) que la machine hôte peut utiliser pour effectuer de façon plus efficace l'arithmétique d'entiers. Par exemple, sur de nombreux ordinateurs de type PC anciens, la valeur sizeof (size_t) serait 4 (octets) mais sizeof (int) serait 2 (octet). L'arithmétique 16 bits était plus rapide que l'arithmétique 32 bits, bien que le processeur puisse gérer un espace mémoire (logique) de 4 Gio.

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 (short) <= sizeof (int) <= sizeof (long) ne limitant pas la représentation réelle de la précision disponible pour le programmeur ces types primitifs.

Note: Ceci n'est PAS le même qu'en Java (qui spécifie en fait la précision des bits pour chacun des types 'char', 'byte', 'short', 'int' et 'long').


48
2017-09-25 07:31



Type size_t doit être assez grand pour stocker la taille de tout objet possible. Unsigned int ne doit pas 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 assez grand pour stocker des nombres supérieurs à 4G.


23
2017-09-25 07:08



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

Il y a un problème potentiel avec le type size_t et les versions de GCC avant la version 2.4. ANSI C exige que size_t soit toujours un type non signé. Pour 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 'le définit comme étant. La plupart des systèmes Unix qui définissent size_t dans `sys / types.h ', le définissent comme un type signé. Certains codes de la bibliothèque dépendent de taille_t étant un type non signé, et ne fonctionnera pas correctement si elle est signée.

Le code de la bibliothèque GNU C qui s'attend à ce que size_t soit non 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 comme un type non signé, et le fixincludes' script will massage the system'ssys / types.h 'pour ne pas entrer en conflit avec cela.

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


3
2017-09-24 02:44



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.


2
2018-01-19 20:55



size_t est la taille d'un pointeur.

Donc, dans 32 bits ou le modèle ILP32 commun (entier, long, pointeur), la taille du modèle est de 32 bits. et dans 64 bits ou le commun LP64 (long, pointeur) le modèle size_t est de 64 bits (les entiers sont toujours 32 bits).

Il y a d'autres modèles mais ce sont ceux que g ++ utilise (au moins par défaut)


-3
2017-09-27 05:21