Вопрос

У меня есть следующий код на C #:

byte rule = 0;
...
rule = rule | 0x80;

который выдает ошибку:

Не удается неявно преобразовать тип 'int' в 'byte'.Существует явное преобразование (вам не хватает приведения?)

[Обновить:первая версия вопроса была неверной ...Я неправильно истолковал вывод компилятора]

Добавление приведенного состава не делает устраните проблему:

rule = rule | (byte) 0x80;

Мне нужно написать это следующим образом:

rule |= 0x80;

Что просто кажется странным.Почему это происходит |= оператор, чем-либо отличающийся от | оператор?

Есть ли какой-либо другой способ сообщить компилятору, чтобы он обрабатывал константу как байт?


@ Giovanni Galbo :и да, и нет.Код имеет дело с программированием флэш-памяти во внешнем устройстве и логически представляет собой один байт памяти.Я мог бы разыграть его позже, но это казалось более очевидным.Я думаю, мое наследие Си слишком сильно проявляется!

@ Джонатан Холланд :синтаксис 'as' выглядит аккуратнее, но, к сожалению, похоже, что он не работает ...это производит:

Оператор as должен использоваться со ссылочным типом или типом с нулевым значением ('byte' - это ненулевой тип значения).

Это было полезно?

Решение

int rule = 0;
rule |= 0x80;

http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx Оператор | определен для всех типов значений.Я думаю, что это приведет к желаемому результату.Оператор "|=" - это оператор or then assign , который является просто сокращением для rule = rule | 0x80.

Одна из самых замечательных особенностей C # заключается в том, что она позволяет вам делать сумасшедшие вещи, такие как злоупотребление типами значений, просто основываясь на их размере.'Int' - это точно то же самое, что и байт, за исключением того, что компилятор будет выдавать предупреждения, если вы попытаетесь использовать их как оба одновременно.Простое использование одного из них (в данном случае int) работает хорошо.Если вас беспокоит 64-разрядная готовность, вы можете указать int32, но все целые значения являются int32, даже если они работают в режиме x64.

Другие советы

В C # нет буквального суффикса для byte.u = uint, l = long, ul = ulong, f = float, m = десятичная дробь, но без байта.Вы должны разыграть его.

Это работает:

rule = (byte)(rule | 0x80);

Очевидно, что выражение 'rule | 0x80' возвращает значение int, даже если вы определяете 0x80 как 'постоянный байт 0x80'.

Термин, который вы ищете, - "Буквальный", и, к сожалению, в C # нет байтового литерала.

Вот список все литералы C #.

В соответствии с Спецификация ECMA, стр. 72 здесь нет байтового литерала.Только целочисленные литералы для типов:int, uint, длинный и улонг.

Похоже, вам, возможно, просто придется сделать это уродливым способом: http://msdn.microsoft.com/en-us/library/5bdb6693.aspx.

Прошло почти пять лет, а никто так и не ответил на этот вопрос.

В паре ответов утверждается, что проблема заключается в отсутствии байтового литерала, но это не имеет значения.Если вы рассчитаете (byte1 | byte2) результат имеет вид int.Даже если бы "b" было буквальным суффиксом для байта, тип (23b | 32b) все равно было бы int.

Принятый ответ ссылается на статью MSDN, в которой утверждается, что operator| определено для всех целых типов, но это также неверно.

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

rule = (byte)(rule | 0x80);

Остается вопрос, почему это происходит rule |= 0x80; работать?

Потому что в спецификации C # есть специальное правило для составного присваивания, которое позволяет вам опустить явное преобразование.В составном задании x op= y это правило таково:

если выбранный оператор является предопределенным оператором, если возвращаемый тип выбранного оператора явно преобразуется в тип x, и если y неявно преобразуется в тип x или оператор является оператором сдвига, то операция оценивается как x = (T)(x op y), где T - тип x, за исключением того, что x вычисляется только один раз.

К сожалению, ваш единственный выход - сделать это именно так, как у вас есть.Нет суффикса для обозначения литерала как байта.Оператор | не предусматривает неявного преобразования в виде присваивания (т. е.инициализация) была бы.

Очевидно, что выражение 'rule | 0x80' возвращает значение int, даже если вы определяете 0x80 как 'постоянный байт 0x80'.

Я думаю, что правило заключается в том, что числа типа 0x80 по умолчанию имеют значение int, если вы не включаете буквенный суффикс.Итак , для выражения rule | 0x80, результатом будет значение int, поскольку 0x80 является значением int, а правило (которое является байтом) может быть безопасно преобразовано в значение int.

Согласно стандарту C, байты ВСЕГДА преобразуются в int в выражениях, даже в константах.Однако, пока оба значения БЕЗ ЗНАКА, биты старшего порядка будут отброшены, поэтому операция должна вернуть правильное значение.

Аналогично, значения float увеличиваются в два раза и т.д.

Вытащите копию K & R.Все это есть там.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top