31

所以我正在构建一个 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 提出这个问题,我都找不到答案。

请帮我 :)

4

2 回答 2

32

移位运算符的定义是指 32 位数字只使用最低 5 位,64 位只使用前 6 位;意义:

1 << 5

等同于_

1 << 37

(两者都是32

通过制作:

MsgrVersion9 = 1L << 32

您将其设为 64 位数字,这就是 @leppie 的修复有效的原因;否则首先<<考虑the (并注意, ie相同),然后将结果转换为 a ; 所以它仍然是。1<<32 1<<011long1

从 ECMA 规范中的 §14.8 开始:

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

  • x的类型为intoruint时,移位计数由 count 的低五位给出。换句话说,移位计数是从 计算的count & 0x1F
  • x的类型为longor时,移位计数由countulong的低六位给出。换句话说,移位计数是从 计算的。count & 0x3F

如果结果移位计数为零,则移位运算符简单地返回 x 的值。

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

于 2011-05-05T08:10:47.313 回答
10

问题可能与算术溢出有关。

具体在:

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

我建议你这样做:

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

防止意外溢出。

更新:

似乎较小的数字“触及”31 位,而较大的数字“触及”32 位。

于 2011-05-05T07:17:45.920 回答