Atrapando el desbordamiento de unsigned int: Detective de C++ desde cero hasta experto

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Trampa para los desprevenidos: ¿por qué unsigned int es una bomba de tiempo?

\n\n

Todo desarrollador de C++ tarde o temprano se encuentra con una situación en la que los números se comportan como conejos enojados: saltan infinitamente de positivo a cero. Hablamos del desbordamiento de unsigned int. A diferencia de su contraparte con signo (signed int), el desbordamiento de unsigned en C++ está estrictamente definido por el estándar — no es UB (comportamiento indefinido). El número simplemente se envuelve módulo 2N. Pero esto no hace que el error sea menos fatal.

\n\n

Imagina: calculas el saldo de una cuenta, la cantidad de elementos en un arreglo o el tiempo de funcionamiento de un temporizador. Un desbordamiento accidental y la lógica de la aplicación se derrumba. La pregunta del título "How do I detect unsigned integer overflow?" acumuló miles de visitas en Stack Overflow por una razón. Analicemos tres enfoques para la detección de desbordamiento: desde el ingenuo (pero funcional) hasta el profesional.

\n\n

¿Por qué no funcionan las comprobaciones estándar?

\n\n

Lo primero que se le ocurre a un principiante:

\n\n
unsigned int a = UINT_MAX;\nunsigned int b = 1;\nif (a + b < a) // Comprobación ingenua\n    std::cout << "¡Desbordamiento!";
\n\n

Este código funciona, pero solo para la suma. Para la multiplicación, resta o tipos mixtos, la lógica se rompe. Además, el compilador puede considerar esta comprobación como redundante y eliminarla durante la optimización. Especialmente si los tipos tienen signo. No confíes en la magia: escribe explícitamente.

\n\n

Enfoque n.º 1: Aritmética antes de la operación (Pre-check)

\n\n

La forma más confiable es verificar la posibilidad de desbordamiento antes de realizar la operación. Para la suma de dos números sin signo, la condición es simple:

\n\n

Si a + b puede desbordarse, entonces a > (UINT_MAX - b).

\n\n
#include <climits>\n#include <iostream>\n\nbool will_add_overflow(unsigned int a, unsigned int b) {\n    return a > UINT_MAX - b;\n}\n\nint main() {\n    unsigned int x = 4000000000;\n    unsigned int y = 500000000;\n    \n    if (will_add_overflow(x, y)) {\n        std::cerr << "Error: ¡desbordamiento en la suma!\\n";\n    } else {\n        std::cout << "Resultado: " << x + y << "\\n";\n    }\n    return 0;\n}
\n\n

Multiplicación: más compleja

\n

Para la multiplicación, la comprobación es un poco más ingeniosa: a > UINT_MAX / b (y no olvides la división por cero).

\n\n
bool will_mult_overflow(unsigned int a, unsigned int b) {\n    if (b == 0) return false; // Multiplicar por cero es seguro\n    return a > UINT_MAX / b;\n}
\n\n

Ventajas: Multiplataforma, control total, sin dependencias ocultas.
\nDesventajas: Necesitas escribir funciones separadas para cada operación. El código se vuelve voluminoso.

\n\n

Enfoque n.º 2: Comprobación después de la operación (Post-check)

\n\n

El estándar de C++ garantiza que para tipos unsigned, el resultado de una operación es (a + b) mod 2^N. Por lo tanto, podemos realizar la operación y luego verificar si el valor se "envolvió".

\n\n
#include <iostream>\n#include <limits>\n\ntemplate<typename T>\nbool add_overflow(T a, T b, T& result) {\n    result = a + b;\n    return result < a; // Truco clave\n}\n\nint main() {\n    unsigned int res;\n    if (add_overflow(4000000000u, 500000000u, res)) {\n        std::cout << "¡Desbordamiento detectado!\\n";\n    } else {\n        std::cout << "OK: " << res << "\\n";\n    }\n    return 0;\n}
\n\n

Importante: Este truco funciona solo si a y b son del mismo tipo sin signo. Para uint32_t es excelente. Para una mezcla de unsigned int e int es un fracaso.

\n\n

Trampa para la resta

\n

Para la resta, la condición es la inversa: result > a.

\n\n
template<typename T>\                

Blogs

Book Recommendations