Подтвердить что ты не робот

Проблемы с FlagsAttribute Enum

Итак, я создаю клиент MSNP (Windows Live Messenger). И у меня есть этот список возможностей

public enum UserCapabilities : long
{
    None = 0,
    MobileOnline = 1 << 0,
    MSN8User = 1 << 1,
    RendersGif = 1 << 2,
    ....
    MsgrVersion7 = 1 << 30,
    MsgrVersion8 = 1 << 31,
    MsgrVersion9 = 1 << 32,
}

полный список здесь http://paste.pocoo.org/show/383240/

Сервер отправляет каждому пользователю возможности как длинное целое число, которое я беру и передаю его в UserCapabilities

capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;

Это нормально, и, по крайней мере, один пользователь (со значением возможности 1879474220), я могу сделать

Debug.WriteLine(_msgr.GetUser(usr).Capabilities);

и это выведет

RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7

Но с другим пользователем, у которого есть значение возможности (3055849760), когда я делаю то же самое, я получаю только тот же номер, который выдает

3055849760

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

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

Пожалуйста, помогите мне:)

4b9b3361

Ответ 1

Определение операторов сдвига означает, что для 32-битных чисел используются только 5 наименее значимых битов и только первые 6 бит для 64-битного; что означает:

1 << 5

является идентичным до

1 << 37

(оба значения 32)

Сделав это:

MsgrVersion9 = 1L << 32

вы делаете это 64-битным числом, поэтому работа с @leppie работает; в противном случае << считается first (и обратите внимание, что 1<<32 идентичен 1<<0, т.е. 1), а , затем полученный 1 преобразуется в long; поэтому он еще 1.

Из §14.8 в спецификации ECMA:

Для предопределенных операторов число битов сдвига вычисляется следующим образом:

  • Когда тип x равен int или uint, счетчик сдвига задается младшими пятью битами счета. Другими словами, подсчет сдвига вычисляется из count & 0x1F.
  • Когда тип x равен long или ulong, счетчик сдвига задается шестью битами младшего разряда. Другими словами, подсчет сдвига вычисляется из count & 0x3F.

Если итоговое значение сдвига равно нулю, операторы сдвига просто возвращают значение x.

Операции сдвига никогда не вызывают переполнения и не дают одинаковых результатов в проверенном и непроверенном контексте

Ответ 2

Проблема может заключаться в арифметическом переполнении.

В частности:

MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,

Я предлагаю вам сделать это:

MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,

Во избежание случайного переполнения.

Update:

Похоже, что меньшее число на "касается" 31 бит, а большее - "32".