Como sabemos, el desbordamiento de enteros con signo es un comportamiento indefinido . Pero hay algo interesante en la cstdint
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 el complemento a 2 para valores negativos (proporcionado solo si la implementación admite directamente el tipo)
Y aquí es mi pregunta: ya que la norma dice explícitamente que para int8_t
, int16_t
, int32_t
y int64_t
los números negativos son complemento a 2, sigue siendo desbordamiento de estos tipos un comportamiento indefinido?
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 al 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 de entero con signo con un ancho de exactamente 8 bits.
Respuestas:
Si. Según el párrafo 5/4 del estándar C ++ 11 (con respecto a cualquier expresión en general):
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.
Con respecto a la aritmética sin signo , por otro lado, el Estándar especifica explícitamente que (Párrafo 3.9.1 / 4):
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 al pie 46 explica esto:
fuente
El hecho de que un tipo esté definido para usar la representación del complemento a 2, no implica que el desbordamiento aritmético en ese tipo se defina.
El comportamiento indefinido del desbordamiento aritmético firmado se utiliza para habilitar optimizaciones; por ejemplo, el compilador puede asumir que si
a > b
entoncesa + 1 > b
también; esto no se cumple en la aritmética sin firmar, donde la segunda verificación debería realizarse debido a la posibilidad de quea + 1
pueda llegar a0
. Además, algunas plataformas pueden generar una señal de captura en caso de desbordamiento aritmético (ver, por ejemplo, http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html ); el estándar continúa permitiendo que esto ocurra.fuente
abs
. Para esas operaciones cuando funciona no requiere más instrucciones que con artmética firmada.(int)(x+y)>z
, compararía un resultado ajustado), y también permitiría a los programadores escribirx+y>z
en los casos en que sería aceptable que el código arrojara 0 o 1 en caso de de desbordamiento siempre que no tenga otros efectos secundarios . Si 0 o 1 fuera un resultado igualmente aceptable, dejar que el programador escriba eso en lugar de cualquiera de los dos(long)x+y>z
o(int)((unsigned)x+y)>z
permitiría a los compiladores seleccionar cualquiera de las últimas funciones que fuera más barata en cualquier contexto dado [cada una sería más barata en algunos casos].Apuesto a que sí.
De la documentación estándar (páginas 4 y 5):
fuente