¿El desbordamiento de enteros con signo sigue siendo un comportamiento indefinido en C++?
Como sabemos, el desbordamiento de enteros con signo es un comportamiento indefinido . Pero hay algo interesante en cstdint
la documentación de C++11:
tipo entero con signo con un ancho de exactamente 8, 16, 32 y 64 bits respectivamente, sin bits de relleno y usando complemento a 2 para valores negativos (proporcionado solo si la implementación admite directamente el tipo)
Ver enlace
Y aquí está mi pregunta: dado que el estándar dice explícitamente que para int8_t
, y los números negativos son complemento a 2, ¿sigue siendo el desbordamiento de estos tipos un comportamiento indefinido?int16_t
int32_t
int64_t
Editar Revisé los estándares C++11 y C11 y esto es lo que encontré:
C++11, §18.4.1:
El encabezado define todas las funciones, tipos y macros igual que 7.20 en el estándar C.
C11, §7.20.1.1:
El nombre typedef
intN_t
designa un tipo entero con signo con ancho N, sin bits de relleno y una representación en complemento a dos. Por lo tanto,int8_t
denota un tipo entero con signo con un ancho de exactamente 8 bits.
¿Sigue siendo el desbordamiento de estos tipos un comportamiento indefinido?
Sí. Según el párrafo 5/4 del estándar C++11 (con respecto a cualquier expresión en general):
Si durante la evaluación de una expresión, el resultado no está definido matemáticamente o no está en el rango de valores representables para su tipo, el comportamiento es indefinido . [...]
El hecho de que se utilice una representación en complemento a dos para esos tipos con signo no significa que se utilice módulo aritmético 2^n al evaluar expresiones de esos tipos.
En cuanto a la aritmética sin signo , por otra parte, la Norma especifica explícitamente que (Párrafo 3.9.1/4):
Los enteros sin signo, declarados
unsigned
, obedecerán las leyes de la aritmética módulo 2^n donde n es el número de bits en la representación del valor de ese tamaño particular de entero.
Esto significa que el resultado de una operación aritmética sin signo siempre está " definido matemáticamente " y el resultado siempre está dentro del rango representable; por lo tanto, 5/4 no se aplica. La nota a pie de página 46 explica esto:
46) Esto implica que la aritmética sin signo no se desborda porque un resultado que no puede representarse mediante el tipo entero sin signo resultante se reduce en módulo el número que es uno mayor que el valor más grande que puede representarse mediante el tipo entero sin signo resultante.
El hecho de que un tipo esté definido para utilizar la representación en complemento a 2 no significa que se defina el desbordamiento aritmético en ese tipo.
El comportamiento indefinido del desbordamiento aritmético con signo se utiliza para permitir optimizaciones; por ejemplo, el compilador puede asumir que si a > b
entonces a + 1 > b
también; esto no se cumple en la aritmética sin signo donde sería necesario realizar la segunda verificación debido a la posibilidad de que a + 1
podría llegar a 0
. Además, algunas plataformas pueden generar una señal trampa en caso de desbordamiento aritmético (consulte, por ejemplo, http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html ); la norma continúa permitiendo que esto ocurra.