Qu'est-ce que size_t en C?
Je suis de se confondre avec l' size_t
en C. je sais que c'est renvoyé par la sizeof
de l'opérateur. Mais qu'en est-il exactement? Est-il un type de données?
Disons que j'ai un for
boucle:
for(i = 0; i < some_size; i++)
Dois-je utiliser int i;
ou size_t i;
?
- Si ce sont vos seules options, utilisez
int
sisome_size
est signé,size_t
si elle n'est pas signée. - C'est incorrect. POSIX a un ssize_t type, mais le fait correct à utiliser est ptrdiff_t.
Vous devez vous connecter pour publier un commentaire.
À Partir De Wikipedia:
Comme conséquence,
size_t
est un type de garantie afin de conserver tous les index de tableau.size_t
est pour les objets en mémoire. La norme n'a même pas définirstat()
ouoff_t
(ceux qui sont POSIX définitions) ou quelque chose à faire avec des disques ou des systèmes de fichiers - il s'arrête de lui-même àFILE
ruisseaux. De gestion de mémoire virtuelle est complètement différent de systèmes de fichiers et de gestion de fichiers taille des exigences, afin de mentionneroff_t
est pas pertinente ici.size_t
que le type du résultat de lasizeof
opérateur (7.17p2 sur<stddef.h>
). La Section 6.5 explique exactement comment C les expressions de travail (6.5.3.4 poursizeof
). Puisque vous ne pouvez pas appliquersizeof
dans un fichier sur disque (surtout parce que C n'a même pas de définir la façon dont les disques et les fichiers de travail), il n'y a pas de place pour la confusion. En d'autres termes, la faute à Wikipédia (et cette réponse pour la citation de Wikipédia et non le C standard).size_t
est (presque certainement) un typedef pour certains type entier non signé. Par exemple,size_t
est généralement du même type queunsigned long
(un typedef crée un alias pour un type existant, pas d'un nouveau type). Mais vous ne devriez pas supposer quesize_t
est le même que n'importe quel type particulier, puisqu'il peut varier d'un système à l'autre.size_t
est un type non signé. Donc, il ne peut pas représenter toutes les valeurs négatives(<0). Vous l'utilisez lorsque vous êtes en comptant quelque chose, et que vous êtes sûr qu'il ne peut pas être négative. Par exemple,strlen()
renvoie unesize_t
, car la longueur d'une chaîne de caractères doit être d'au moins 0.Dans votre exemple, si votre indice de boucle va être toujours supérieure à 0, il pourrait être judicieux d'utiliser
size_t
, ou de toute autre unsigned type de données.Lorsque vous utilisez un
size_t
objet, vous devez vous assurer que dans tous les contextes, il est utilisé, y compris l'arithmétique, vous voulez valeurs non négatives. Par exemple, disons que vous avez:et vous voulez savoir la différence de la longueur des
str2
etstr1
. Vous ne pouvez pas faire:C'est parce que la valeur attribuée à
diff
est toujours un nombre positif, même lorsques2 < s1
, parce que le calcul est fait avec des types non signés. Dans ce cas, selon ce que votre cas d'utilisation, vous pourriez être mieux à l'aide deint
(oulong long
) pours1
ets2
.Il y a quelques fonctions en C/POSIX qui pourrait/devrait utiliser
size_t
, mais n'est pas à cause de raisons historiques. Par exemple, le deuxième paramètre àfgets
devrait idéalement êtresize_t
, mais estint
.size_t
? 2) pourquoi devrais-je préfèresize_t
plus de quelque chose commeunsigned int
?size_t
n'est pas garanti d'être la même chose queunsigned int
(vous semblent être ce qui implique qu'ils sont les mêmes).size_t
estsizeof(size_t)
. La norme garantit queSIZE_MAX
sera au moins égale à 65 535.size_t
est le type retourné parsizeof
opérateur, et est utilisé dans la bibliothèque standard (par exemplestrlen
retournesize_t
). Comme Brendan dit,size_t
n'a pas besoin d'être le même queunsigned int
.size_t
n'est pas le même queunsigned int
, je suppose que vous voulez dire qu'il n'est pas garanti d'être unint
, mais il est en faitunsigned
. Est-ce vrai?size_t
est garanti d'être un type non signé.s1
ets2
sont à la fois d'un type non signé (size_t
par exemple), le résultats1-s2
pas être négatif, même lorsques1 < s2
. C'est parce que les types non signés n'ont pas de valeurs négatives. Lorsque vous attribuer cette différence à uneint
, le résultat est la mise en œuvre définies. Qui était le point entier de dire que l'on ne veut pas prendre la différence des types non signés dans mon exemple, parce que l'on a d'être en mesure d'obtenir de façon portable la possible différence négative.size_t s2 = 5, s1 = 20; int diff = s2 - s1; printf("%d: %x\n", diff, diff < 0);
Cette affiche exactement ce que vous attendez:"-15: 1"
s2 - s1
déborde unint
, le comportement est indéfini.size_t
est un type qui peut contenir n'importe quel tableau d'index.En fonction de la mise en œuvre, il peut être tout de:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Voici comment
size_t
est défini dansstddef.h
de ma machine:typedef unsigned long size_t
est dépendant du compilateur. Ou êtes-vous croire qu'il est toujours ainsi?unsigned long
est de 32 bits,size_t
est de 64 bits.size_t
est toujours 32bits sur 32 bits machine 64bits de même?unsigned char
?uint_least16_t
est ce qu'au moins 16 bits. À propos,size_t
, le standard dit "non signé intégrale type du résultat de l'opérateur sizeof" et "L'opérateur sizeof donne la taille (en octets) de son opérande".unsigned char
ne peut pas être de 16 bits?!unsigned char
contient au moins les valeurs0-255
.Si vous êtes le empiriques de type,
De sortie pour Ubuntu 14.04 64 bits GCC 4.8:
Noter que
stddef.h
est fourni par GCC et non de la glibc soussrc/gcc/ginclude/stddef.h
dans GCC 4.2.Intéressant C99 apparences
malloc
prendsize_t
comme argument, il détermine la taille maximale pouvant être alloués.Et depuis il est également renvoyé par
sizeof
, je pense qu'il limite la taille maximale d'un tableau.Voir aussi: Quelle est la taille maximale d'un tableau en C?
size_t
est, au moins sur la populaire distribution Linux.La page de manuel pour les types.h dit:
Puisque personne n'a encore mentionné, le principal linguistique de la signification de
size_t
est que lesizeof
opérateur renvoie une valeur de ce type. De même, l'importance deptrdiff_t
est que la soustraction d'un pointeur à partir d'un autre donnera une valeur de ce type. Bibliothèque de fonctions qui acceptent de le faire, car il va permettre de telles fonctions pour travailler avec des objets dont la taille dépasse UINT_MAX sur les systèmes sur lesquels de tels objets existent, sans forcer les appelants pour le code déchets en passant d'une valeur supérieure à "unsigned int" sur les systèmes où le plus grand type suffirait pour que tous les objets possibles.malloc()
. Personnellement, j'aurais aimé avoir vu les versions qui prennent des arguments de typeint
,long
, etlong long
, avec certaines implémentations de la promotion de la plus courte des types et des autres, la mise en œuvre par exemplelmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}
[sur certaines plates-formes, appelant àimalloc(123)
serait moins cher que d'appelerlmalloc(123);
, et même sur une plate-forme oùsize_t
est de 16 bits, le code qui souhaite allouer la taille calculée dans une "longue" de la valeur...size_t
etint
ne sont pas interchangeables. Par exemple, sur Linux 64 bitssize_t
est de 64 bits (c'est à diresizeof(void*)
) maisint
est de 32 bits.Également noter que
size_t
est pas signé. Si vous avez besoin signé, puis il estssize_t
sur certaines plates-formes et il serait plus pertinent de votre exemple.En règle générale, je voudrais suggérer à l'aide de
int
pour la plupart des cas généraux et d'utiliser uniquementsize_t
/ssize_t
lorsqu'il existe un besoin pour elle (avecmmap()
par exemple).Aller dans pourquoi
size_t
besoin d'exister et comment nous en sommes arrivés là:Pragmatique,
size_t
etptrdiff_t
sont garantis 64 bits sur une version 64 bits de mise en œuvre, 32 bits de large sur 32 bits et la mise en œuvre, et ainsi de suite. Ils ne pouvaient pas la force de tout type existant pour dire que, sur chaque compilateur, sans enfreindre le code de legs.Un
size_t
ouptrdiff_t
n'est pas nécessairement la même que pour unintptr_t
ouuintptr_t
. Ils étaient différents sur certaines architectures qui étaient encore en usage lors de lasize_t
etptrdiff_t
ont été ajoutées à la Norme à la fin des années ’80, et de devenir obsolète quand C99 a ajouté beaucoup de nouveaux types, mais pas encore parti (comme Windows 16 bits). Le x86 16 bits en mode protégé avait une segmentation de la mémoire, où le plus grand nombre possible de tableau ou de la structure pourrait être seulement de 65 536 octets la taille, mais unfar
pointeur nécessaires à 32 bits de large, plus large que les registres. Sur ceux,intptr_t
aurait été de 32 bits de large, maissize_t
etptrdiff_t
pourrait être de 16 bits de large et s'inscrire dans un registre. Et qui savait ce type de système d'exploitation peut être écrit dans l'avenir? En théorie, l'architecture i386 propose une version 32 bits de modèle de segmentation avec 48 bits pointeurs qu'aucun système d'exploitation n'a jamais réellement utilisé.Le type d'un décalage mémoire n'a pas pu être
long
parce que beaucoup trop de code hérité suppose quelong
est exactement 32 bits de large. Cette hypothèse a même été intégré dans les environnements UNIX et Windows Api. Malheureusement, beaucoup d'autres l'héritage de code suppose également qu'unelong
est assez large pour contenir un pointeur, un fichier de contrepartie, le nombre de secondes qui se sont écoulées depuis 1970, et ainsi de suite. POSIX maintenant fournit une méthode normalisée pour la force de cette dernière hypothèse soit vraie place de l'ancien, mais il n'est ni un portable hypothèse à faire.Il ne pouvait pas être
int
parce que seule une petite poignée de compilateurs dans les années ’90 faitint
64 bits de large. Puis ils vraiment se sont bizarres en gardantlong
32 bits de large. La prochaine révision de la Norme déclaré illégal pourint
à être plus large quelong
, maisint
est toujours de 32 bits de large sur la plupart des systèmes 64 bits.Il ne pouvait pas être
long long int
, qui de toute façon a été ajoutée plus tard, depuis qu'a été créé pour être au moins 64 bits, même sur les systèmes 32 bits.Ainsi, un nouveau type a été nécessaire. Même si ce n'était pas le cas, tous ceux d'autres types signifiait autre chose que d'un décalage à l'intérieur d'un tableau ou d'un objet. Et si il y avait une leçon à tirer de l'fiasco de 32 à 64 bits de la migration, c'était d'être précis sur ce que les propriétés d'un type de besoin d'avoir, et de ne pas utiliser l'un qui signifie différentes choses dans différents programmes.
En général, si vous êtes en commençant à 0 et allez vers le haut, toujours utiliser un type non signé afin d'éviter un débordement de vous emmenant à une valeur négative de la situation. Cela est extrêmement important, parce que si votre limites du tableau se trouve être inférieur au max de votre boucle, mais votre boucle max arrive à être plus grande que le maximum de votre type, vous enrouler autour de négatif et vous pouvez rencontrer un erreur de segmentation (SIGSEGV). Donc, en général, ne jamais utiliser d'int pour une boucle commençant à 0 et va vers le haut. Utiliser un unsigned.
size_t est entier non signé de type de données. Sur les systèmes à l'aide de la Bibliothèque C de GNU, ce sera unsigned int ou unsigned longue int. size_t est couramment utilisé pour le tableau d'indexation et boucle de comptage.
size_t ou tout type non signé peut être vu utilisé comme variable de boucle en boucle variables sont généralement supérieur ou égal à 0.
Lorsque nous utilisons un size_t objet, nous devons nous assurer que, dans tous les contextes, il est utilisé, y compris l'arithmétique, nous ne voulons que la non-valeurs négatives. Par exemple, à la suite du programme serait certainement donner le résultat inattendu:
À partir de ma compréhension,
size_t
est ununsigned
entier dont la taille en bits est assez grand pour contenir un pointeur de l'architecture native.Donc:
size_t
. Plusieurs exemple: les compilateurs C sur x86 en mode réel peut avoir 32 bitsFAR
ouHUGE
pointeurs mais size_t est encore en 16 bits. Un autre exemple: Watcom C permet d'avoir une graisse spéciale pointeur de la mémoire étendue qui était de 48 bits de large, maissize_t
ne l'était pas. Sur le contrôleur embarqué avec Harvard architecture, vous n'avez pas de corrélation soit, parce que les deux préoccupations différentes des espaces d'adressage.size_t