Что на самом деле происходит при переполнении байта? - PullRequest
15 голосов
/ 11 ноября 2010

Что на самом деле происходит при переполнении байта?

Скажем, у нас есть

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

Если мы сейчас сделаем это добавление

byte byte3 = byte1 + byte2;

Я думаю, что мы закончимс byte3 = 94, но что на самом деле происходит?Я как-то перезаписал какую-то другую память или это совершенно безвредно?

Ответы [ 12 ]

11 голосов
/ 11 ноября 2010

Это довольно просто. Он просто добавляет сложение и имеет число более 8 бит. Девятый бит (равный единице) просто «падает», и у вас остаются 8 оставшихся битов, которые образуют число 94.

(да, это безвредно)

7 голосов
/ 11 ноября 2010

В C #, если у вас есть

 checked { byte byte3 = byte1 + byte2; }

Это вызовет исключение переполнения.Код компилируется unchecked по умолчанию.Как говорят другие ответы, значение будет «перевернуто».т.е. byte3 = (byte1 + byte2) & 0xFF;

6 голосов
/ 11 ноября 2010

Старшие биты будут усечены.Он не вреден для любой другой памяти, он вреден только с точки зрения непредвиденных результатов.

5 голосов
/ 11 ноября 2010

Поскольку вы отметили свой вопрос C #, C ++ и C, я отвечу о C и C ++. В C ++ переполнение для подписанных типов, включая sbyte (которое, я считаю, signed char в C / C ++), приводит к неопределенному поведению. Однако для типов без знака, таких как byte (что в C ++ равно unsigned char), результат получается по модулю 2 n , где n - количество бит в типе без знака. В C # выполняется второе правило, и подписанные типы генерируют исключение, если они находятся в блоке checked. Я могу ошибаться в части C #.

5 голосов
/ 11 ноября 2010

Как правило (и точное поведение будет зависеть от языка и платформы), результат будет взят по модулю 256. то есть 150 + 199 = 349. 349 мод 256 = 93.

Это не должно влиять на любое другое хранилище.

5 голосов
/ 11 ноября 2010

Флаг переноса устанавливается ... но кроме того, что результат не соответствует вашим ожиданиям, не должно быть вредных последствий.

4 голосов
/ 11 ноября 2010

Переполнение безвредно в C # - вы не переполните память - вы просто получите последние 8 бит результата. Если вы хотите, чтобы это исключение, используйте ключевое слово «флажок». Также обратите внимание, что вы можете обнаружить, что byte + byte дает int, поэтому вам может потребоваться привести обратно к байту.

3 голосов
/ 11 ноября 2010

Поведение зависит от языка.

В C и C ++ переполнение со знаком не определено, а переполнение без знака имеет указанное вами поведение (хотя нет типа byte).

В C # вы можете использовать ключевое слово checked, чтобы явно сказать, что вы хотите получить исключение, если есть переполнение, и ключевое слово unchecked, чтобы явно сказать, что вы хотите его игнорировать.

2 голосов
/ 11 ноября 2010

И происходит арифметическое переполнение.Поскольку 150 + 199 = 349, двоичное 1 0101 1101, старший 1 бит сбрасывается, и байт становится 0101 1101;т. е. число битов, которые может удерживать байт, переполнено.

Никаких повреждений не было - например, память не переполнилась в другое место.

2 голосов
/ 11 ноября 2010

Ведущий бит только что упал.

...