Aritmética de C++ con tipos integrales mixtos que provocan desbordamiento
-
21-12-2019 - |
Pregunta
He realizado algunas pruebas en VC++2010 mezclando operandos de diferentes tamaños que causan desbordamiento en la operación de adición:
int _tmain(int argc, _TCHAR* argv[])
{
__int8 a=127;
__int8 b=1;
__int16 c=b+a;
__int8 d=b+a;
printf("c=%d,d=%d\n",c,d);
return 0;
}
//result is: c=128, d=-128
¡No entiendo por qué c==128!Tengo entendido que en ambas sumas, b+a todavía se considera suma de 2 signos 8 bits variables.Entonces el resultado es un desbordamiento, es decir-128. Después, el resultado luego se promueve a int con signo de 16 bits para la primera operación de asignación y c aún debería obtener un valor -128 de 16 bits.¿Es correcto mi entendimiento?El estándar C++ es un poco difícil de leer.El capítulo 4 parece hablar de promoción entera pero no puedo encontrar nada relacionado con este ejemplo específico.
Solución
Tengo entendido que en ambas adiciones, b+a todavía se considera una suma de 2 variables de 8 bits con signo.Entonces el resultado es un desbordamiento, es decir-128.
No, la promoción ocurre antes del +
se evalúa, no después de ello.La suma ocurre cuando ambos a
y b
son positivos.Ambos números ascienden a int
s para una suma, sumados como dos números positivos y luego convertidos a un corto de 16 bits.En ningún momento del proceso el resultado se vuelve negativo debido a un desbordamiento, de ahí el resultado final de 128.
Podría decirse que esto tiene sentido:el comportamiento de a
y b
coincide con el de dos números en matemáticas, haciéndolo más intuitivo para los profesionales del lenguaje.
Otros consejos
Es promoción integral.
1 Un valor pr de un tipo entero distinto de bool, char16_t, char32_t o wchar_t cuyo rango de conversión de entero (4.13) es menor que el rango de int se puede convertir en un valor pr de tipo int si int puede representar todos los valores del tipo fuente ;de lo contrario, el valor pr de origen se puede convertir en un valor pr de tipo int sin signo.[§ 4.5]
En esta declaración
__int16 c=b+a;
Primeramente
char
yshort int
Los valores se elevan automáticamente aint
.Este proceso se llama promoción integral.A continuación, todos los operandos se convierten al tipo del operando más grande, que se llama tipo promoción.[Herbert Schildt]
El valores de variables b
y a
será ascendido a int
y luego la operación se aplica sobre ellos.
En la representación de enteros en complemento a dos, un valor con signo se representa estableciendo el bit más alto.Esto permite a la máquina sumar y restar números enteros binarios con las mismas instrucciones, independientemente de si el número entero tiene signo.
a = 127 == 0x7F == 0b01111111
+ b = 1 == 0x01 == 0b00000001
-------------------------------
c = 128 == 0x80 == 0b10000000
d =-128 == 0x80 == 0b10000000
las variables c
y d
Puede tener diferentes tipos, pero diferentes tipos de números enteros son simplemente interpretaciones diferentes de un único valor binario.Como puede ver arriba, el valor binario cabe perfectamente en 8 bits.Dado que el estándar requiere que los términos de una expresión matemática se extiendan (promuevan) con cero o signos al tamaño de una palabra de máquina antes Se realizan todos los cálculos y ningún operando tendrá extensión de signo, el resultado siempre es 0b10000000
no importa de qué tipo sean los operandos.
En resumen, la diferencia entre los resultados es que, para un entero de 16 bits, el bit de signo es 0b1000000000000000
(cual a+b
no tiene), y para un entero de 8 bits el bit de signo es 0b10000000
(cual a+b
si tiene).