unsigned int vs size_t
Je remarque que la modernité de code C et C++ semble utiliser size_t
au lieu de int
/unsigned int
un peu partout - à partir de paramètres pour C les fonctions de chaîne à la STL. Je suis curieux de savoir la raison de cette et les avantages qu'elle apporte.
Vous devez vous connecter pour publier un commentaire.
La
size_t
type est le type entier non signé qui est le résultat de lasizeof
de l'opérateur (et leoffsetof
de l'opérateur), de sorte qu'il est garanti d'être assez grand pour contenir la taille du plus grand objet de votre système (par exemple, un tableau statique de 8 go).La
size_t
type peut être plus grande que, égal ou plus petit qu'ununsigned int
, et votre compilateur peut faire des hypothèses à ce sujet pour l'optimisation.Vous pouvez trouver plus d'informations précises dans le standard C99, section 7.17, dont un projet est disponible sur Internet dans pdf format, ou dans la norme C11, l'article 7.19, également disponible en tant que pdf projet.
size_t
peut représenter! Si elle ne le fait pas, qui le fait?size_t
, parce que les types non signés sont plus strictement défini et donc (dans certaines circonstances) vérifier, pour dépassement de capacité, entre autres choses. Comparé à d'autres types non signés, les opérations simples comme pointeur/tableau d'indexation peut-être encore plus rapide, parce que le compilateur pourrait par exemple ne pas avoir à convertir les entiers 64 bits en premier (si votre PROCESSEUR n'effectue de l'arithmétique des pointeurs en 64 bits).2 * sizeof(T)
GO d'éléments, je vous recommande fortement de stockage de votre tableau des tailles et des indices commeint
au lieu desize_t
chaque fois que vous pouvez sortir avec elle. Peut vous faire économiser jusqu'à 50% de la mémoire, et peut même accélérer la vitesse de votre code.int
s et de les changer tous les non signé, sans aucun problème. Je suis d'accord qu'il ya des moments où unint
a ses mérites (y compris le fait que certains appels les utiliser comme de la prise de fonctions!) mais il n'est pas toujours une décision facile à prendre (bien que parfois il est facile de faire).Classique C (le début du dialecte de C décrite par Brian Kernighan et Dennis Ritchie dans Le Langage de Programmation C, Prentice-Hall, 1978) n'a pas fournir
size_t
. Le C comité des normes introduitessize_t
pour éliminer un problème de portabilitéExpliqué en détail lors de embedded.com (avec un très bon exemple)
En bref,
size_t
n'est jamais négatif, et il optimise les performances, car il est typedef pour être le type entier non signé qui est assez grand, mais pas trop grand -- pour représenter la taille de la plus grande possible de l'objet sur la plate-forme cible.Tailles ne doivent jamais être négatif, et en effet
size_t
est un type non signé. Aussi, parce quesize_t
est pas signé, vous pouvez stocker les numéros qui sont à peu près deux fois plus grande que dans le type signé, parce que nous pouvons utiliser le bit de signe pour représenter l'ampleur, comme tous les autres bits de l'entier non signé. Quand nous gagnons un peu plus, nous sommes en multipliant la plage de nombres, nous pouvons représente par un facteur de deux.Donc, vous demandez-vous, pourquoi ne pas simplement utiliser un
unsigned int
? Il peut ne pas être en mesure de tenir assez grand nombre. Dans une application oùunsigned int
est de 32 bits, le plus grand nombre, il peut représenter est4294967295
. Certains processeurs, tels que la IP16L32, vous pouvez copier des objets de plus de4294967295
octets.Donc, vous demandez-vous, pourquoi ne pas utiliser un
unsigned long int
? Elle exige une performance sans frais sur certaines plates-formes. C Standard exige qu'unlong
occuper au moins 32 bits. Un IP16L32 plate-forme met en œuvre chaque long 32 bits comme une paire de mots de 16 bits. Presque tous les 32-bit les opérateurs sur ces plates-formes ont besoin de deux instructions, si pas plus, parce qu'ils travaillent avec le 32 bits dans deux de 16 bits morceaux. Par exemple, le déplacement d'un long 32 bits nécessite généralement deux instructions machine, l'une pour le déplacement de chaque 16 bits morceau.À l'aide de
size_t
évite cette performance sans frais. Selon ce fantastique article, "Typesize_t
est une définition de type qui est un alias pour certains type entier non signé, généralementunsigned int
ouunsigned long
, mais peut-être mêmeunsigned long long
. Chaque Norme C mise en œuvre est censé choisir le nombre entier non signé qui est assez grand--mais pas plus grand que nécessaire--pour représenter la taille de la plus grande possible de l'objet sur la plate-forme cible."unsigned int
peut varier d'un système à l'autre. Il est nécessaire de au moins65536
, mais il est communément4294967295
et pourrait être18446744073709551615
(2**64-1) sur certains systèmes.unsigned char
). La norme ne semble pas contenir la chaîne de caractères "65535" ou "65536" n'importe où, et '+32767' ne se produit (1.9:9) dans une note que possible le plus grand entier représentable dansint
; aucune garantie n'est donnée même queINT_MAX
ne peut pas être plus petit que!<climits>
: "Le contenu est le même que la bibliothèque Standard C de l'en-tête<limits.h>
". J'avais suppose que les exigences en termes de contenu sont les mêmes. C99 dit dans 5.2.4.2.1/1 "Leur mise en œuvre-la définition des valeurs doit être égale ou de plus grande ampleur (valeur absolue) à celles indiquées, avec le même signe.", suivi par les valeurs elles-mêmes.SIZE_MAX
etUINT_MAX
et tout en elleULONG_MAX
(voir les fichiers d'en-têtestdint.h
etlimits.h
). Bien sûr, c'est pour le C - j'ai eu une très mauvaise réaction de C++, mais même alors, il y a toujours des limites.Le type size_t est le type retourné par l'opérateur sizeof. Il est un entier non signé capable d'exprimer la taille en octets de mémoire pris en charge sur la machine hôte. Il est (généralement) liées à ptrdiff_t dans ce ptrdiff_t est un entier signé valeur tels que sizeof(ptrdiff_t) et sizeof(size_t) sont égaux.
Lors de l'écriture de code C, vous devez toujours utilisation size_t chaque fois que de traiter avec des plages de mémoire.
Le type int sur l'autre main est essentiellement définie comme la taille de l' (signé) valeur entière que la machine hôte peut utiliser le plus efficacement possible d'effectuer l'arithmétique des nombres entiers. Par exemple, sur de nombreux anciens de type PC ordinateurs de la valeur de sizeof(size_t) serait de 4 (octets), mais sizeof(int) serait de 2 (octet). 16 bits arithmétique a été plus rapide que le 32 bits, l'arithmétique, bien que le PROCESSEUR peut gérer une (logique) de l'espace mémoire de 4 Go.
Utiliser le type int seulement quand vous vous souciez de l'efficacité réelle de la précision dépend fortement sur les deux options du compilateur et de l'architecture de la machine. En particulier, la norme spécifie les éléments suivants invariants: sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) sans autres limitations de la représentation réelle de la précision à la disposition du programmeur pour chacun de ces types de primitives.
Remarque: Ce n'est PAS le même qu'en Java (ce qui indique le peu de précision pour chacun des types de 'char', 'octet', 'courte', 'int' et 'long').
size_t
est capable de représenter la taille d'un objet unique (par exemple: nombre, tableau, structure). L'ensemble de la plage de mémoire peut dépassersize_t
Type size_t doit être assez grand pour stocker la taille de n'importe quel objet possible. Unsigned int n'a pas à satisfaire à cette condition.
Par exemple dans les systèmes 64 bits int et unsigned int peut être de 32 bits de large, mais size_t doit être assez grand pour stocker des nombres plus grands que la 4G
size_t
aurait seulement besoin d'être grand si le compilateur pourrait accepter un type de X tels que sizeof(X) donnerait une valeur plus grande que la 4G. La plupart des compilateurs de se faire rejeter par exempletypedef unsigned char foo[1000000000000LL][1000000000000LL]
, et mêmefoo[65536][65536];
pourrait légitimement être rejeté s'il a dépassé une documentation de mise en œuvre-limite définie.Cet extrait de la glibc manuel de 0,02, peuvent également être utiles lors de la recherche de la rubrique:
Il y a un problème potentiel avec le type size_t et versions de GCC avant la version 2.4. ANSI C exige que size_t toujours être d'un type non signé. Pour la compatibilité avec les systèmes de fichiers d'en-tête, GCC définit size_t dans
stddef.h' to be whatever type the system's
sys/types.h' définit qu'il soit. La plupart des systèmes Unix qui définissent size_t dans `sys/types.h', de définir un type signé. Un peu de code dans la bibliothèque dépend size_t être un type non signé, et ne fonctionnera pas correctement si elle est signée.La bibliothèque C de GNU code, qui prévoit que la size_t être non signé est correct. La définition de size_t comme un type signé est incorrect. Nous prévoyons que dans la version 2.4, GCC sera toujours définir size_t comme un type non signé, et la
fixincludes' script will massage the system's
sys/types.h " afin de ne pas entrer en conflit avec cette.Dans l'intervalle, nous contourner ce problème en disant GCC explicitement à l'utilisation d'un type non signé pour size_t lors de la compilation de la bibliothèque C de GNU. "configurer" détecte automatiquement quel type de GCC utilise pour size_t organiser pour le remplacer si nécessaire.
Si mon compilateur est de 32 bits,
size_t
est rien d'autre qu'un typedef pourunsigned int
. Si mon compilateur est réglé sur 64 bits,size_t
est rien d'autre qu'un typedef pourunsigned long long
.unsigned long
pour les deux cas sur certains Systèmes d'exploitation.size_t est la taille d'un pointeur.
Donc en 32 bits ou la commune ILP32 (integer, long, pointeur) modèle size_t est de 32 bits.
et en 64 bits ou la commune LP64 (long, pointeur) modèle size_t est de 64 bits (entiers sont encore en 32 bits).
Il y a d'autres modèles, mais ce sont ceux que g++ utilisation (au moins par défaut)
size_t
n'est pas nécessairement la même taille qu'un pointeur, mais il est généralement. Un pointeur doit être capable de pointer vers n'importe quel emplacement mémoire;size_t
ne doit être suffisamment grand pour représenter la taille de la plus grande d'un seul objet.