Quelle est la différence entre size_t et int en C ++?

173

Dans plusieurs exemples C ++, je vois une utilisation du type size_toù j'aurais utilisé un simple int. Quelle est la différence et pourquoi size_tdevrait-elle être meilleure?

Tunnuz
la source
3
Pour un exemple réel où ils ne sont pas interchangeables, voir une question que j'ai posée précédemment: stackoverflow.com/questions/645168/…
Tyler McHenry

Réponses:

153

Du sympathique Wikipedia :

Les fichiers d'en-tête stdlib.h et stddef.h définissent un type de données appelé size_t qui est utilisé pour représenter la taille d'un objet. Les fonctions de bibliothèque qui prennent des tailles s'attendent à ce qu'elles soient de type size_t, et l'opérateur sizeof est évalué à size_t.

Le type réel de size_t dépend de la plate-forme; une erreur courante est de supposer que size_t est identique à unsigned int, ce qui peut conduire à des erreurs de programmation, d'autant plus que les architectures 64 bits deviennent plus courantes.

Vérifiez également pourquoi size_t est important

Joao da Silva
la source
76
Et donc, qu'est-ce que size_t?
EMI du
8
@NDEthos Cela dépend! Ici, Linux /usr/include/stdlib.hobtient la définition à partir de laquelle /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.helle est par défaut à long unsigned intmoins qu'un autre fichier d'en-tête ne dise le contraire.
David Tonhofer le
1
Je confirme que size_t à int tuncation est dangereux . Cela peut être hors sujet, mais comment écrire un correctif seul pour corriger ce genre d'erreurs quand cela se produit des milliers de fois dans le noyau Linux?
user2284570
36

size_t est le type utilisé pour représenter les tailles (comme son nom l'indique). Sa plate-forme (et même potentiellement sa mise en œuvre) dépendante, et ne doit être utilisée qu'à cette fin. Évidemment, représentant une taille, size_t n'est pas signé. De nombreuses fonctions stdlib, y compris malloc, sizeof et diverses fonctions d'opération de chaîne utilisent size_t comme type de données.

Un int est signé par défaut, et même si sa taille dépend également de la plate-forme, ce sera un 32 bits fixe sur la plupart des machines modernes (et bien que size_t soit 64 bits sur une architecture 64 bits, int reste 32 bits de long sur ces architectures).

Pour résumer: utilisez size_t pour représenter la taille d'un objet et int (ou long) dans les autres cas.

Axelle Ziegler
la source
12

Le size_ttype est défini comme le type intégral non signé de l' sizeofopérateur. Dans le monde réel, vous verrez souvent intdéfini comme 32 bits (pour la compatibilité descendante) mais size_tdéfini comme 64 bits (vous pouvez donc déclarer des tableaux et des structures de plus de 4 Gio) sur les plates-formes 64 bits. Si a long intest également 64 bits, cela s'appelle la convention LP64; si long intest 32 bits mais long long intet les pointeurs sont 64 bits, c'est LLP64. Vous pouvez également obtenir l'inverse, un programme qui utilise des instructions 64 bits pour la vitesse, mais des pointeurs 32 bits pour économiser de la mémoire. En outre, intest signé et size_tn'est pas signé.

Il y avait historiquement un certain nombre d'autres plates-formes où les adresses étaient plus larges ou plus courtes que la taille native de int. En fait, dans les années 70 et au début des années 80, c'était plus courant qu'autrement: tous les micro-ordinateurs 8 bits populaires avaient des registres 8 bits et des adresses 16 bits, et la transition entre 16 et 32 ​​bits produisait également de nombreuses machines qui avaient des adresses plus larges que leurs registres. Je vois encore parfois des questions ici sur Borland Turbo C pour MS-DOS, dont le mode de mémoire Énorme avait des adresses 20 bits stockées en 32 bits sur un processeur 16 bits (mais qui pourrait prendre en charge le jeu d'instructions 32 bits du 80386); le Motorola 68000 avait une ALU 16 bits avec registres et adresses 32 bits; il y avait des mainframes IBM avec des adresses 15 bits, 24 bits ou 31 bits. Vous voyez également toujours différentes tailles d'ALU et de bus d'adresses dans les systèmes embarqués.

Chaque fois intque l' heure est inférieure à size_t, et que vous essayez de stocker la taille ou le décalage d'un fichier ou d'un objet très volumineux dans un unsigned int, il est possible que cela déborde et provoque un bogue. Avec un int, il y a aussi la possibilité d'obtenir un nombre négatif. Si un intou unsigned intest plus large, le programme fonctionnera correctement mais gaspillera de la mémoire.

Vous devez généralement utiliser le type correct à cette fin si vous voulez la portabilité. Beaucoup de gens vous recommanderont d'utiliser des mathématiques signées au lieu de non signées (pour éviter des bogues méchants et subtils comme 1U < -3). Pour cela, la bibliothèque standard définit ptrdiff_tin <stddef.h>comme le type signé du résultat de la soustraction d'un pointeur d'un autre.

Cela dit, une solution de contournement pourrait être de vérifier les limites de toutes les adresses et décalages par rapport à l' INT_MAXun 0ou l' autre ou INT_MINselon le cas, et d'activer les avertissements du compilateur concernant la comparaison des quantités signées et non signées au cas où vous en manqueriez. Vous devriez toujours, toujours, toujours vérifier vos accès aux tableaux pour un débordement en C de toute façon.

Davislor
la source
8

C'est parce que size_t peut être autre chose qu'un int (peut-être une structure). L'idée est qu'elle dissocie son travail du type sous-jacent.

graham.reeds
la source
8
Je pense que size_t est en fait garanti pour être un alias pour un entier non signé, donc ce ne peut pas être une structure. Je n'ai pas de référence à portée de main pour étayer cela pour le moment, cependant.
détendre le
9
@unwind: C99: TC3, 7.17 §2
Christoph
1
@danio Pourquoi est-ce ainsi? pouvez-vous expliquer?
Le vautour de Rüppell
2
Je ne créerais pas de lien vers cplusplus si j'étais vous! Si vous ne pouvez pas citer un chapitre, un verset, un paragraphe et une ligne, ce n'est que du ouï-dire! :-)
graham.reeds
1
size_test spécifié comme un type entier non signé . C11 §6.5.3.4 5 "La valeur du résultat des deux opérateurs ( sizeof _Alignof) est définie par l'implémentation et son type (un type entier non signé) est size_t,".
chux
-1

La définition de SIZE_Tse trouve à: https://msdn.microsoft.com/en-us/library/cc441980.aspx et https://msdn.microsoft.com/en-us/library/cc230394.aspx

Collez ici les informations requises:

SIZE_Test un ULONG_PTRreprésentant le nombre maximum d'octets vers lesquels un pointeur peut pointer.

Ce type est déclaré comme suit:

typedef ULONG_PTR SIZE_T;

A ULONG_PTRest un type long non signé utilisé pour la précision du pointeur. Il est utilisé lors de la conversion d'un pointeur vers un type long pour effectuer l'arithmétique du pointeur.

Ce type est déclaré comme suit:

typedef unsigned __int3264 ULONG_PTR;
sundar
la source
2
SIZE_Tn'est pas size_t, ce que le PO a demandé.
ikegami
2
C'est une extension Microsoft, qui ne fait pas partie du langage standard.
Davislor
SIZE_Test totalement différent de size_t. Vous ne pouvez pas déclarer une variable de type SIZE_T.
calocedrus