Las variables enteras firmadas no tienen un comportamiento envolvente en el lenguaje C. El desbordamiento entero firmado durante los cálculos aritméticos produce comportamiento indefinido. Nota Por cierto, que el compilador GCC que mencionó es conocido por implementar Semántica de desbordamiento estricto En optimizaciones, lo que significa que aprovecha la libertad proporcionada por tales situaciones de comportamiento indefinidas: el compilador de GCC asume que los valores de enteros firmados nunca se extienden. Eso significa que el GCC en realidad es uno de los compiladores en los que no poder Confíe en el comportamiento envolvente de los tipos enteros firmados.
Por ejemplo, el compilador de GCC puede suponer que para la variable int i
la siguiente condición
if (i > 0 && i + 1 > 0)
es equivalente a un mero
if (i > 0)
Esto es exactamente lo que Semántica de desbordamiento estricto medio.
Los tipos enteros sin firmar implementan la aritmética de módulos. El módulo es igual 2^N
dónde N
es el número de bits en la representación de valor del tipo. Por esta razón, los tipos de enteros sin firmar parecen envolver sobre el desbordamiento.
Sin embargo, el lenguaje C nunca realiza cálculos aritméticos en dominios más pequeños que el de int
/unsigned int
. Escribe unsigned short int
que mencionas en tu pregunta normalmente será promovido para escribir int
en expresiones antes de que comiencen cualquier cálculo (suponiendo que el rango de unsigned short
encaja en el rango de int
). Lo que significa que 1) los cálculos con unsigned short int
se preformará en el dominio de int
, con el desbordamiento sucediendo cuando int
Los desbordamientos, 2) el desbordamiento durante tales cálculos conducirá a un comportamiento indefinido, no a un comportamiento envolvente.
Por ejemplo, este código produce una envoltura
unsigned i = USHRT_MAX;
i *= INT_MAX; /* <- unsigned arithmetic, overflows, wraps around */
Mientras este código
unsigned short i = USHRT_MAX;
i *= INT_MAX; /* <- signed arithmetic, overflows, produces undefined behavior */
conduce a un comportamiento indefinido.
Si no int
El desbordamiento ocurre y el resultado se convierte en un unsigned short int
Tipo, nuevamente se reduce por Modulo 2^N
, que aparecerá como si el valor hubiera envuelto.