Почему при сложении byte не переполняется?

269
30 августа 2017, 13:16

Есть вот такой очень простой код.

using System;
class Test
{       
    static void Main()
    {
        byte x = byte.Parse(Console.ReadLine());
        byte y = byte.Parse(Console.ReadLine());
        Console.WriteLine(x + y);
    }
}

При вводе 123 и 221 выводит 344. Но ведь должно было произойти переполнение, почему оно не произошло? Почему не вывело 344 - 255 = 89?

Answer 1

Отличный вопрос!

Согласно спецификации языка, определены следующие операторы числового сложения:

int operator +(int x, int y);
uint operator +(uint x, uint y);
long operator +(long x, long y);
ulong operator +(ulong x, ulong y);
float operator +(float x, float y);
double operator +(double x, double y);
decimal operator +(decimal x, decimal y);

Сложение байтов не определено. Таким образом, язык применяет конверсию, и превращает byte в int, чтобы использовать int operator +(int x, int y);.

Правила конверсии описаны здесь (перевод мой):

Расширение типов для бинарных операторов состоит в применении следующих правил в том порядке, в каком они специфицированы тут:

  • Если хотя бы один из операндов имеет тип decimal, другой операнд преобразуется в тип decimal, или возникает ошибка времени привязки типов, если тип другого операнда — float или double.
  • Иначе, если тип хотя бы одного из операндов double, другой операнд преобразуется в double.
  • Иначе, если тип хотя бы одного из операндов float, другой операнд преобразуется в float.
  • Иначе, если тип хотя бы одного из операндов ulong, другой операнд преобразуется в ulong, или возникает ошибка времени привязки типов если другой операнд имеет тип sbyte, short, int или long.
  • Иначе, если тип хотя бы одного из операндов long, другой операнд преобразуется в long.
  • Иначе, если тип хотя бы одного из операндов uint и тип другого операнда sbyte, short или int, оба операнда преобразуются в long.
  • Иначе, если тип хотя бы одного из операндов uint, другой операнд преобразуется в uint.
  • Иначе оба операнда преобразуются в int.

В нашем случае работает последний пункт. Значения преобразуются в int до сложения, и тип результата — int.

Answer 2

Дело в том, что результат сложения byte + byte вовсе не обязан иметь тип byte.

На самом деле, результат сложения имеет тип int, в который можно запросто поместить число 334.

А проверить это утверждение можно вот так:

using System;
class Test
{       
    static void Main()
    {
        byte x = 123;
        byte y = 221;
        byte z = x + y;
        Console.WriteLine(z);
    }
}

Приведет к ошибке:

Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)

READ ALSO
Как устроено iocp в System.Net.Socket?

Как устроено iocp в System.Net.Socket?

Как IOCP устроено в нативе - понятноСоздается IO порт, к нему привязываются сокеты

306
Извлечь данные пользователя

Извлечь данные пользователя

Создаю программу "Банкомат"Возник вопрос - как сделать чтобы пользователь ввел свой ид, и сразу показало его счет и фио класс банкомат

317
Запретить повторное открытие tabPage c#

Запретить повторное открытие tabPage c#

Здравствуйте, подскажите пожалуйста, как запретить повторное открытие страницы tabPage1, через buttonТ

271