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

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

Скажем, что

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

Если мы сделаем это дополнение

byte byte3 = byte1 + byte2;

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

Ответы

Ответ 1

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

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

Ответ 2

В С#, если у вас

 checked { byte byte3 = byte1 + byte2; }

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

Переполнение безвредно в С# - вы не будете переполнять память - вы просто обловы получаете последние 8 бит результата. Если вы хотите, чтобы это исключение, используйте ключевое слово "checked". Заметим также, что вы можете найти байт + байт, который дает int, поэтому вам может потребоваться отбросить его в байт.

Ответ 8

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

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

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

Ответ 9

Ведущий бит просто выпал.

Ответ 10

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

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

Ответ 11

Посмотрим, что на самом деле происходит (в C (если у вас есть соответствующий тип данных, так как некоторые указали, что C не имеет типа байтов), тем не менее, существуют 8-битные типы данных, которые могут быть добавлено)). Если эти байты объявлены в стеке, они существуют в основной памяти; в какой-то момент байты будут скопированы в процессор для работы (я пропускаю несколько важных шагов, таких как кэширование процессов...). Однажды в процессоре они будут храниться в регистрах; процессор будет выполнять операцию добавления для этих двух регистров, чтобы добавить данные вместе. Здесь возникает причина путаницы. ЦП будет выполнять операцию добавления в нативном (или иногда заданном) типе данных. Пусть говорят, что родной тип процессора - это 32-битное слово (и этот тип данных - это то, что используется для операции добавления); это означает, что эти байты будут сохранены в 32-битных словах с отмененными верхними 24 битами; операция добавления действительно сделает переполнение в целевом 32-битном слове. Но (и здесь важный бит), когда данные копируются обратно из регистра в стек, только самые младшие 8 бит (байт) будут скопированы обратно в место назначения цели в стеке. (Обратите внимание, что здесь есть и сложность, связанная с упаковкой байтов и стеком.)

Итак, вот итог; добавление вызывает переполнение (в зависимости от выбранной выбранной команды процессора); однако данные копируются из процессора в тип данных соответствующего размера, поэтому переполнение невидимо (и безвредно, если предполагается, что он написан правильно).

Ответ 12

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

Поэтому ваш образец кода приведет к ошибке компилятора без возврата к байту, как показано ниже.

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

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

Подробнее см. в MSDN. Кроме того, см. спецификацию языка С#, раздел 7.3.6 Числовые рекламные акции.