NoP*_*God 31 .net c# enum-flags
所以我正在构建一个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,
}
Run Code Online (Sandbox Code Playgroud)
完整列表http://paste.pocoo.org/show/383240/
服务器将每个用户的功能作为一个长整数发送给客户端,我将其转换为UserCapabilities
capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;
Run Code Online (Sandbox Code Playgroud)
这很好,至少有一个用户(能力值为1879474220),我能做到
Debug.WriteLine(_msgr.GetUser(usr).Capabilities);
Run Code Online (Sandbox Code Playgroud)
这将输出
RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7
Run Code Online (Sandbox Code Playgroud)
但是对于具有(3055849760)能力值的另一个用户,当我这样做时,我只输出相同的数字
3055849760
Run Code Online (Sandbox Code Playgroud)
我希望看到的是功能列表,与其他用户一样.
我确信这种情况有一个非常合理的原因,但无论我多么努力地向谷歌提问,我都找不到答案.
请帮我 :)
Mar*_*ell 32
移位运算符的定义意味着只有5个最低有效位用于32位数,而前6位用于64位; 含义:
1 << 5
Run Code Online (Sandbox Code Playgroud)
是完全相同的
1 << 37
Run Code Online (Sandbox Code Playgroud)
(都是32
)
通过制作:
MsgrVersion9 = 1L << 32
Run Code Online (Sandbox Code Playgroud)
你把它变成64位数,这就是为什么@ leppie的修复工作; 否则<<
被认为是第一(请注意,1<<32
是相同的 1<<0
,即,1
),和然后将所得1
被转换成long
; 所以它仍然是1
.
从ECMA规范中的§14.8开始:
对于预定义的运算符,要移位的位数计算如下:
- 当的类型X是
int
或uint
,移位计数由低阶的5位给出计数.换句话说,移位计数是从count & 0x1F
.- 当x的类型是
long
或时ulong
,移位计数由低位6位计数给出.换句话说,移位计数是从count & 0x3F
.如果得到的移位计数为零,则移位运算符只返回x的值.
Shift操作永远不会导致溢出,并在已检查和未检查的上下文中产生相同的结果
lep*_*pie 10
问题可能是算术溢出.
具体在:
MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
Run Code Online (Sandbox Code Playgroud)
我建议你做到:
MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,
Run Code Online (Sandbox Code Playgroud)
防止意外溢出.
更新:
似乎可能是'触摸'31位上的较小数字,而较大的'触摸'32位.