Числовые константы C # - PullRequest
       60

Числовые константы C #

19 голосов
/ 04 сентября 2008

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

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

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

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

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

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

rule = rule | (byte) 0x80;

Мне нужно написать это как:

rule |= 0x80;

Что кажется странным. Почему оператор |= отличается от оператора |?

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


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

@ Jonathon Holland : синтаксис as выглядит аккуратнее, но, к сожалению, не работает ... он выдает:

Оператор as должен использоваться с ссылочным типом или обнуляемым типом («byte» - тип значения, не допускающий обнуления)

Ответы [ 10 ]

34 голосов
/ 04 сентября 2008

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

11 голосов
/ 04 сентября 2008

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

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

Видимо выражение 'правило | 0x80 'возвращает int, даже если вы определяете 0x80 как' const byte 0x80 '.

9 голосов
/ 04 сентября 2008

Вы ищете термин «Литерал», и, к сожалению, C # не имеет байтового литерала.

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

6 голосов
/ 04 сентября 2008
int rule = 0;
rule |= 0x80;

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

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

3 голосов
/ 04 сентября 2008

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

1 голос
/ 02 июня 2013

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

В нескольких ответах утверждается, что проблема заключается в отсутствии байтового литерала, но это не имеет значения. Если вы вычисляете (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 вычисляется только один раз.

1 голос
/ 04 сентября 2008

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

0 голосов
/ 28 января 2013

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

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

Извлечь копию K & R. Это все там.

0 голосов
/ 04 сентября 2008

Видимо выражение 'правило | 0x80 'возвращает int, даже если вы определить 0x80 как «константный байт 0x80».

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

0 голосов
/ 04 сентября 2008

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

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