C# XOR на двухбайтовых переменных не скомпилирует без броска [дубликат]

Этот вопрос уже имеет ответ здесь:

Почему делает следующее повышение ошибка времени компиляции: 'Не может неявно преобразовать тип 'интервал' в 'байт':

        byte a = 25;
        byte b = 60;

        byte c = a ^ b;

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

Однако применение этого к оператору XOR бессмысленно. XOR здесь это битовая операция, которая никогда не может переполнять байта.

использование броска вокруг обеих работ операндов:

byte c = (byte)(a ^ b);
31
задан Ash 28 April 2010 в 04:57
поделиться

7 ответов

Я не могу дать вам объяснение, но могу сказать, почему компилятор имеет такое поведение с точки зрения правил, которым компилятор должен следовать ( что может быть не совсем то, что вам интересно знать).

Из старой копии спецификации C # (мне, вероятно, следует загрузить более новую версию) добавлено выделение:

14.2.6.2 Двоичные числовые рекламные предложения Этот пункт является информативным.

Двоичное числовое повышение происходит для операндов предопределенных + , ? , * , / , % , & , | , ^ , == , ! = , > , <, > = и <= бинарные операторы. Двоичное числовое продвижение неявно преобразует оба операнда в общий тип, который в случае нереляционных операторов также становится результатом {{1} } тип операции. Двоичное числовое продвижение состоит из применения следующих правил в том порядке, в котором они появляются здесь:

  • Если один из операндов имеет десятичный тип, другой операнд будет {{1} }} преобразуется в тип 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 для этих операторов (и результатом будет int для нереляционных опс).

Я сказал, что не могу дать вам объяснение; однако я сделаю предположение об одном - я думаю, что разработчики C # хотели убедиться, что операции, которые могут потерять информацию в случае сужения, должны иметь эту операцию сужения, явно выраженную программистом в форме приведения. Например:

byte a = 200;
byte b = 100;

byte c = a + b;  // value would be truncated

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


Небольшое примечание: приведенная выше цитата является «информационной», а не «нормативной», но она охватывает все случаи в удобной для чтения форме.Строго говоря (в нормативном смысле), причина того, что оператор ^ ведет себя таким образом, заключается в том, что ближайшая перегрузка для этого оператора при работе с операндами байтом является (из 14.10.1 "Целое число логические операторы "):

int operator ^(int x, int y); 

Поэтому, как объясняется в информативном тексте, операнды повышаются до int , и получается результат int .

25
ответ дан 27 November 2019 в 22:47
поделиться

Похоже, это потому, что в спецификациях языка C # это определено для целых и длинных http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx

Итак, что на самом деле происходит, этот компилятор неявно преобразует байтовые операнды в int, потому что таким образом не происходит потери данных. Но результат (int) не может быть понижен без потери данных (неявно). Итак, вам нужно явно сообщить компилятору, что вы знаете, что делаете!

0
ответ дан 27 November 2019 в 22:47
поделиться

У программиста-полубога из Microsoft есть ответ: http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx

И, возможно, это больше о дизайне компилятора. Они упрощают компилятор, обобщая процесс компиляции, ему не нужно смотреть на оператор операндов, поэтому побитовые операции сосредоточены в той же категории, что и арифметические операторы. Таким образом, подвергается расширению типа

Ссылка мертва, архив здесь:

https://web.archive.org/web/20140118171646/http://blogs.msdn.com/b/oldnewthing/archive/2004/ 03/10 / 87247.aspx

2
ответ дан 27 November 2019 в 22:47
поделиться

Я думаю, это потому, что оператор XOR определен для логических и целых чисел.

Приведение результата из целочисленного результата к байту - это преобразование с потерей информации; следовательно, требуется явное приведение (кивок программиста).

1
ответ дан 27 November 2019 в 22:47
поделиться

Мне показалось, что я вспомнил популярный вопрос об этом.

байт + байт = целое число ... почему?

0
ответ дан 27 November 2019 в 22:47
поделиться

Это больше связано с правилами, окружающими неявное и явное приведение в спецификации CLI. Целое число (int = System.Int32 = 4 байта) шире, чем байт (1 байт, очевидно!). Поэтому любое приведение от int к байту потенциально является сужающим приведением. Поэтому компилятор хочет, чтобы вы сделали это явным.

0
ответ дан 27 November 2019 в 22:47
поделиться

Что касается того, почему два байта должны быть преобразованы в ints для выполнения XOR?

Если вы хотите покопаться в этом, 12.1.2 CLI Spec (раздел I) описывает тот факт, что в стеке оценки могут существовать только int или long. Все более короткие интегральные типы должны быть расширены во время оценки.

К сожалению, я не могу найти подходящую ссылку непосредственно на CLI Spec - у меня есть локальная копия в формате PDF, но я не могу вспомнить, откуда я ее взял.

0
ответ дан 27 November 2019 в 22:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: