2010-11-11 19 views
13

¿Qué sucede realmente cuando se desborda un byte?¿Qué sucede realmente cuando se desborda un byte?

Digamos que tenemos

byte byte1 = 150; // 10010110 
byte byte2 = 199; // 11000111 

Si ahora hacemos esta adición

byte byte3 = byte1 + byte2; 

creo que vamos a terminar con byte3 = 94, pero lo que realmente sucede? ¿Sobreescribí alguna otra memoria de alguna manera o es esto totalmente inofensivo?

+5

Su resultado debe ser 93 ... –

+2

Se eliminaron las etiquetas C y C++ porque A. C y C++ no tienen ningún tipo de datos "byte", y B. es un comportamiento indefinido según el estándar. –

+0

@Billy hay equivalentes en C y C++ –

Respuesta

11

Es bastante simple. Simplemente hace la suma y sale en un número con más de 8 bits. El noveno bit (siendo uno) justo 'se cae' y te quedas con los 8 bits restantes que forman el número 94.

(sí es inofensivo)

+0

Por cierto, algo muy similar sucede con los bytes firmados (u otros tipos numéricos con signo), a excepción de un byte firmado que solo contiene 7 bits de "datos" y un bit para el signo. Esta es la razón por la cual 127 + 1 = -128 para los bytes firmados. (el byte del signo se convierte en 1, lo que significa negativo) – Sam

+0

Aquí hay muchas respuestas excelentes (todo el mundo parecía tener una imagen muy clara de esto, excepto yo :) Es difícil elegir la respuesta, pero elijo que sí. Breve y buena explicación. Gracias a todos – ImJames

+1

Esto no es correcto ya que en C#, el código dado no se compilará. –

5

la bandera de acarreo consigue el sistema ... pero además el resultado no es el esperado, no debe haber efectos negativos.

2

La primera parte acaba de caer.

6

Los bits superiores se truncarán. No es dañino para ninguna otra memoria, solo es dañino en términos de resultados no deseados.

5

Normalmente (y el comportamiento exacto dependerá del idioma y la plataforma), el resultado se tomará como módulo-256. es decir, 150 + 199 = 349. 349 mod 256 = 93.

Esto no debería afectar a ningún otro almacenamiento.

3

El comportamiento depende del idioma.

En C y C++, el desbordamiento con signo no está definido y el desbordamiento sin signo tiene el comportamiento mencionado (aunque no existe el tipo byte).

En C#, puede usar la palabra clave checked para indicar explícitamente que desea recibir una excepción si hay desbordamiento y la palabra clave unchecked para indicar explícitamente que desea ignorarla.

5

Dado que ha etiquetado su pregunta C#, C++ y C, responderé acerca de C y C++. En el desbordamiento de C++ en los tipos firmados, incluido sbyte (que, creo, es signed char en C/C++) da como resultado un comportamiento indefinido. Sin embargo, para los tipos sin firmar, como byte (que es unsigned char en C++) el resultado es toma el módulo 2 n donde n es el número de bits en el tipo sin signo. En C#, la segunda regla se cumple y los tipos firmados generan una excepción si están en el bloque checked. Puedo estar equivocado en la parte de C#.

+0

'byte' es' char sin signo' en WinDef.h. Obviamente * podría * ser cualquier cosa, pero creo que nos preguntan por Windows. –

+0

@steve: ¿He indicado lo contrario? –

+0

@Armen: estoy llamando tu farol. Sí lo hiciste, pero luego editaste. –

2

Y se produce un desbordamiento aritmético. Desde 150 + 199 = 349, binario 1 0101 1101, se suelta el 1 bit superior y el byte se convierte en 0101 1101; es decir, el número de bits que puede contener un byte desbordado.

No se produjo ningún daño - p. la memoria no se desbordó a otra ubicación.

8

En C# si tiene

checked { byte byte3 = byte1 + byte2; } 

Se producirá una excepción de desbordamiento. El código está compilado unchecked de forma predeterminada.Como dicen las otras respuestas, el valor se "ajustará". es decir, byte3 = (byte1 + byte2) & 0xFF;

+0

Este código no se compila. Cuando lo arreglas, la respuesta real se vuelve obvia. –

+1

Cuál, el ejemplo o el ejemplo en línea. ¿Las personas con 3k + rep tienen la opción de corregir las respuestas? –

+0

Esto no es correcto ya que los bytes se promocionan a entradas en la suma, lo que da como resultado un int. Por lo tanto, este código no se compilará sin un molde. –

4

El desbordamiento es inofensivo en C# - no se desbordará la memoria - obtienes obsoletos los últimos 8 bits del resultado. Si desea que esto sea una excepción, use la palabra clave 'checked'. Tenga en cuenta también que puede encontrar byte + byte da int, por lo que es posible que tenga que volver a convertir en byte.

1

Veamos lo que sucede realmente (en C (suponiendo que tiene el tipo de datos apropiado, ya que algunos han señalado que C no tiene un tipo de datos de "byte"; no obstante, existen tipos de datos de 8 bits que pueden ser agregado)). Si estos bytes se declaran en la pila, existen en la memoria principal; en algún punto, los bytes se copiarán al procesador para su operación (me estoy saltando varios pasos importantes, como la caché de procesadores ...). Una vez en el procesador, se almacenarán en registros; el procesador ejecutará una operación de adición sobre esos dos registros para agregar los datos juntos. Aquí es donde ocurre la causa de la confusión. La CPU realizará la operación de agregar en el tipo de datos nativo (o algunas veces, especificado). Digamos que el tipo nativo de la CPU es una palabra de 32 bits (y que ese tipo de datos es lo que se usa para la operación de agregar); eso significa que estos bytes se almacenarán en palabras de 32 bits con los 24 bits superiores desarmados; la operación de agregar hará el desbordamiento en la palabra de 32 bits objetivo. Pero (y aquí está el bit importante) cuando los datos se copian del registro a la pila, solo los 8 bits más bajos (el byte) se copiarán de nuevo a la ubicación de la variable objetivo en la pila. (Tenga en cuenta que aquí también existe cierta complejidad relacionada con el embalaje de bytes y la pila).

Así que aquí está el resultado; el complemento causa un desbordamiento (dependiendo de la instrucción específica del procesador elegida); Sin embargo, los datos se copian del procesador en un tipo de datos del tamaño apropiado, por lo que el desbordamiento no se ve (y es inofensivo, asumiendo un compilador debidamente escrito).

+0

Todo esto para decir que se produjo un desbordamiento aritmético - esta debe ser la razón por la que lo llaman Mc * Waffle * stix

+0

@softwaremonkey: jeje, bueno, la cosa es que no es realmente un desbordamiento aritmético; en el espacio de operación en el que se ejecuta la operación, no hay desbordamiento ni problema. Es útil entender que estas cosas ocurren de la manera en que lo hacen. Además, tenga en cuenta que estaba hablando de C originalmente ... –

1

Por lo que C# va, la adición de dos valores de tipo byte juntos resultados en un valor de tipo int que luego debe ser fundido de nuevo a byte.

Por lo tanto, su ejemplo de código dará como resultado un error del compilador sin un lanzamiento de vuelta al byte como se muestra a continuación.

byte byte1 = 150; // 10010110 
byte byte2 = 199; // 11000111 

byte byte3 = (byte)(byte1 + byte2); 

See MSDN for more details en esto. Además, consulte C# language specification, sección 7.3.6 Promociones numéricas.

Cuestiones relacionadas