标志属性枚举问题

本文关键字:问题 枚举 属性 标志 | 更新日期: 2023-09-27 17:55:22

所以我正在构建一个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

我希望看到的是功能列表,就像其他用户一样。

确信发生这种情况有一个非常正当的理由,但无论我多么努力地向谷歌表达这个问题,我都没有找到答案。

请帮我:)

标志属性枚举问题

移位运算符的定义意味着只有 5 个最低有效位用于 32 位数字,只有前 6 位用于 64 位; 含义:

1 << 5

相同

1 << 37

(两者都是32

通过制作它:

MsgrVersion9 = 1L << 32

你把它变成一个64位的数字,这就是为什么@leppie的修复工作;否则<<被认为是第一个(请注意,1<<321<<0相同,即 1 ),然后将生成的1转换为long;所以它仍然1.

从 ECMA 规范中的 §14.8:

对于预定义的运算符,要移位的位数计算如下:

  • x的类型是intuint时,移位计数由低阶五位计数给出。换句话说,班次计数是从 count & 0x1F 计算的。
  • x的类型是longulong时,移位计数由低阶六位计数给出。换句话说,班次计数是从 count & 0x3F 计算的。

如果生成的移位计数为零,则移位运算符仅返回 x 的值。

移位操作从不会导致溢出,并在检查和未检查的上下文中产生相同的结果

问题可能出在算术溢出上。

具体在:

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

我建议你做到:

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

防止意外溢出。

更新:

似乎可能是"触摸"

31位上的较小数字,而较大的数字"触摸"32位。