为什么我不能将 (1<<31) 分配给 ulong 变量? (错误25 常量值...无法转换...)

Why can't I assign (1<<31) to an ulong var? (Error 25 Constant value ... cannot be converted ...)

为什么这个分配会产生 comile 错误:Constant value '-2147483648' cannot be converted to a 'ulong' 而我必须在这种情况下使用 unchecked (...)

ulong xDummy30 = (1 << 30); // works
ulong xDummy31 = (1 << 31); // ERROR 25 Constant value '-2147483648' cannot be converted to a 'ulong'
ulong xDummy32 = (1 << 32); // works

使用这个代替有效:

ulong xDummy31a = unchecked((ulong)(1 << 31));
// or
ulong xDummy31b = (1ul << 31); //  comment from Regis Portalez

编辑
问题 Why do I have to cast 0 (zero) when doing bitwise operations in C#? 有类似的答案,并且观察到的行为的原因是相同的。但它们是不同的问题。

    var a = (1<<31);
    Console.WriteLine(a);

    ulong num = unchecked((ulong)(1<<31));
    Console.WriteLine(num);

Output:
-2147483648
18446744071562067968

1<<31 值无法放入 uInt64

https://dotnetfiddle.net/Widget/TfjnSZ

根据MSDN ulong reference,您所有的整数文字 1、30、31 都被视为 int:

When an integer literal has no suffix, its type is the first of these types in which its value can be represented: int, uint, long,

根据 MSDN << operator << 操作的结果也是一个 int。当你移位 30 时结果为正,当移位 31 时结果为负整数,不能分配给 ulong。

编辑:HVD 在下面指出了我的错误。谢谢 HVD!

开始错误 - 当移位32位时,编译器知道你要的是ulong,因此移位操作的结果是一个正long,可以转换为unlong - 结束错误

1<<32 不会导致编译器错误的正确原因在于提供给运算符 <<:

的 link

If the first operand is an int, the shift count is given by the low-order five bits of the second operand. That is, the actual shift count is 0 to 31 bits.

32转二进制:0010 0000;低五位:0 0000,所以实际执行的shift是1 << 0,结果是int值为1,当然可以赋值给一个ulong。

要解决这个问题,请确保您的数字 1 是长整数。在那种情况下 1<<31 仍然是正多头。

You can also use suffixes to specify the type of the literal according to the following rules: If you use L, the type of the literal integer will be either long or ulong according to its size.

所以1L是长的; 1L <<31 是一个正 long,因此可以分配给一个 ulong

作为我的问题的补充,此处接受的答案是一个注释:

先引用我问题的例子:

ulong xDummy30 = (1 << 30); // works
ulong xDummy31 = (1 << 31); // ERROR 25 Constant value '-2147483648' cannot be converted to a 'ulong'
ulong xDummy32 = (1 << 32); // works

这个赋值是正确的 没有编译错误:

ulong xDummy32 = (1 << 32);

但它 不 "work",这与我在问题中写的相反。在此之后 xDummy32 的结果不是 4294967296 而是 1。因此移位 > 30 必须这样写:

ulong xDummy32 = (1UL << 32);