Les variables entières signées n'ont pas de comportement enveloppant dans le langage C. Le débordement entier signé pendant les calculs arithmétiques produit comportement non défini. Remarque BTW que le compilateur GCC que vous avez mentionné est connu pour la mise en œuvre Sémantique de débordement stricte Dans les optimisations, ce qui signifie qu'il tire parti de la liberté fournie par de telles situations de comportement non définies: le compilateur GCC suppose que les valeurs entières signées ne s'enroulent jamais. Cela signifie que GCC se trouve en fait être l'un des compilateurs dans lesquels vous ne peux pas Comptez sur le comportement enveloppant des types entiers signés.
Par exemple, le compilateur GCC peut supposer que pour la variable int i
la condition suivante
if (i > 0 && i + 1 > 0)
équivaut à un simple
if (i > 0)
C'est exactement ce Sémantique de débordement stricte moyens.
Les types entiers non signés implémentent l'arithmétique modulo. Le modulo est égal 2^N
où N
est le nombre de bits dans la représentation de valeur du type. Pour cette raison, les types entiers non signés semblent effectivement enrouler sur un débordement.
Cependant, le langage C n'effectue jamais de calculs arithmétiques dans des domaines plus petits que celui de int
/unsigned int
. Taper unsigned short int
que vous mentionnez dans votre question sera généralement promu pour taper int
dans les expressions avant le début des calculs (en supposant que la gamme de unsigned short
s'intègre dans la gamme de int
). Ce qui signifie que 1) les calculs avec unsigned short int
sera préformé dans le domaine de int
, avec un débordement qui se produit quand int
Les débordements, 2) le débordement pendant de tels calculs conduiront à un comportement non défini, et non au comportement de l'enroulement.
Par exemple, ce code produit une enveloppe
unsigned i = USHRT_MAX;
i *= INT_MAX; /* <- unsigned arithmetic, overflows, wraps around */
Alors que ce code
unsigned short i = USHRT_MAX;
i *= INT_MAX; /* <- signed arithmetic, overflows, produces undefined behavior */
conduit à un comportement indéfini.
Sinon int
un débordement se produit et le résultat est converti en un unsigned short int
type, il est à nouveau réduit par modulo 2^N
, qui apparaîtra comme si la valeur était enroulée.