En el lenguaje C, las operaciones aritméticas con tipos enteros pueden llevar a un desbordamiento (overflow) cuando el resultado excede el rango representable del tipo, por ejemplo, int o unsigned int. La especificidad del comportamiento en caso de desbordamiento está determinada por los estándares del lenguaje.
El desbordamiento con tipos con signo (signed overflow) conduce a un undefined behavior, es decir, el compilador tiene el derecho de realizar cualquier acción: ignorar el error, generar una excepción o dejar un resultado impredecible. Para los tipos sin signo (unsigned), según el estándar C, el comportamiento en caso de desbordamiento es definido: ocurre un reinicio por módulo del tamaño del tipo (wraparound).
Para números unsigned, el resultado del desbordamiento es fácilmente predecible, por ejemplo, UINT_MAX + 1 == 0. Para números signed, se recomienda verificar los límites del tipo antes de las operaciones utilizando macros de <limits.h> o emplear herramientas de análisis estático. Los compiladores y herramientas modernas pueden detectar desbordamientos potenciales.
Ejemplo de código:
#include <stdio.h> #include <limits.h> int add_with_check(int a, int b) { if (a > 0 && b > INT_MAX - a) { printf("¡Se producirá un desbordamiento! "); return -1; } return a + b; } int main() { int x = INT_MAX, y = 1; printf("Resultado: %d ", add_with_check(x, y)); unsigned int ux = UINT_MAX; printf("Desbordamiento unsigned: %u ", ux + 1); return 0; }
Características clave:
<limits.h> para obtener los tamaños de los tipos¿Es el desbordamiento del tipo unsigned un error?
No, este comportamiento está definido por el estándar y es equivalente a un reinicio por módulo. Por ejemplo, (unsigned int)UINT_MAX + 1 == 0 siempre es cierto.
¿Se puede contar con que al producirse un desbordamiento int el resultado simplemente "saltará" por encima de INT_MIN?
No, tal comportamiento no está garantizado ni estandarizado, es un comportamiento indefinido. Puede fallar, dar un valor incorrecto (diferente en plataformas) o ser optimizado por el compilador de manera impredecible.
¿Se puede confiar en que el int siempre sea de complemento a dos?
Aunque el hardware moderno prácticamente siempre utiliza "complemento a dos" para representar int con signo, el lenguaje C no lo requiere estándar, por lo que el código con desbordamientos no será portable.
Suma de números int sin verificación de límites: el desbordamiento en grandes conjuntos de datos conduce a cálculos no válidos.
Ventajas:
Desventajas:
Antes de todas las operaciones aritméticas, se realiza una verificación de desbordamiento utilizando macros y funciones. Uso de unsigned donde el wraparound es aceptable.
Ventajas:
Desventajas: