Cela dépend, car size_t
est un type intégral non signé défini par l'implémentation.
Les opérations impliquant un size_t
introduiront donc des promotions, mais celles-ci dépendent de ce que sont effectivement size_t
et des autres types impliqués dans l'expression.
Si size_t
était équivalent à un unsigned short
(par exemple un type 16 bits), puis
size_t foo = 1;
foo += 1;
serait (sémantiquement) promouvoir foo
à un int
, ajouter 1
, puis convertir le résultat à size_t
pour le stockage au foo
. (Je dis "sémantiquement", parce que c'est la signification du code selon la norme.) Un compilateur est libre d'appliquer la règle "comme si" - c'est-à-dire faire ce qu'il veut, pourvu qu'il produise le même effet net).
D'un autre côté, si size_t
était équivalent à un long long unsigned
(par exemple un type signé 64 bits), le même code favoriserait 1
être de type long long unsigned
, l'ajouter à la valeur de foo
, et stocker le résultat retour au foo
. Dans les deux cas, le résultat net est le même sauf si un débordement se produit. Dans ce cas, il n'y a pas de débordement, étant donné qu'un int
et size_t
sont garantis capables de représenter les valeurs 1
et 2
.
Si un dépassement survient (par exemple en ajoutant une valeur intégrale plus grande), alors le comportement peut varier. Le dépassement d'un type intégral signé (par exemple int
) entraîne un comportement indéfini. Le dépassement d'un type intégral unsigned
utilise l'arithmétique modulo.
En ce qui concerne le code
size_t foo = SIZE_MAX;
foo += 1;
il est possible de faire le même genre d'analyse.
Si size_t
est équivalent à unsigned short
, alors foo
sera converti en int
. Si int
est équivalent à signed short
, il ne peut pas représenter la valeur SIZE_MAX
, de sorte que la conversion déborde et le résultat est un comportement indéfini. Si int
est en mesure de représenter une plus grande plage que short int
(par exemple, il est équivalent à long
), puis la conversion de foo
à int
réussira, incrémenter cette valeur réussira, et le stockage de retour à size_t
utilisera l'arithmétique modulo et produire le résultat de 0
.
Si size_t
est équivalent à unsigned long
, alors la valeur 1
seront automatiquement converties en unsigned long
, ajoutant à foo
utilisera arithmétique modulo (à savoir produire un résultat égal à zéro), et qui seront stockées dans foo
.
Il est possible de faire des analyses similaires en supposant que size_t
est réellement d'autres types intégraux non signés.
Remarque: Dans les systèmes modernes, un size_t
de même taille ou plus petit qu'un int
est inhabituel. Toutefois, de tels systèmes ont existé (par exemple, les compilateurs Microsoft et Borland C qui ciblent MS-DOS 16 bits sur du matériel avec un processeur 80286). Des microprocesseurs 16 bits sont encore en production, principalement pour les systèmes embarqués à faible consommation d'énergie et à faible débit, et les compilateurs C qui les ciblent (par exemple le compilateur Keil C166 qui cible la famille de microprocesseurs Infeon XE166). [Note: Je n'ai jamais eu de raison d'utiliser le compilateur Keil mais, étant donné sa plate-forme cible, il ne serait pas surprenant qu'il prenne en charge un size_t
16 bits de même taille ou plus petit que le type natif int
sur cette plate-forme ]
Bonne question. Par expérience, 'size_t' est de la même taille ou plus grand que' int' sur toutes les implémentations que j'ai jamais utilisées. Si nous étions autorisés à appliquer le bon sens (ce que bien sûr nous ne sommes pas), nous noterions qu'un int est la taille "naturelle" pour un type entier sur une implémentation donnée, et donc cela n'aurait aucun sens pour que size_t soit plus petit que cette taille naturelle. – user3386109
Notez que 'SIZE_MAX' n'a pas été défini par la norme C89. –
S'agit-il de la norme actuelle ou C89? – 2501