题
考虑一下这个
int i = 2147483647;
var n = i + 3;
i = n;
Console.WriteLine(i); // prints -2147483646 (1)
Console.WriteLine(n); // prints -2147483646 (2)
Console.WriteLine(n.GetType()); // prints System.Int32 (3)
我对以下内容感到困惑
- (1) int 如何保存值 -2147483646 ?(整数范围 = -2,147,483,648 至 2,147,483,647)
- (2)为什么此打印-2147483648而不是2147483648(编译器应在INT范围超过的情况下决定更好的类型)
- (3)如果它转换在某个地方,为什么n.getType()给出system.int32?
编辑1: 进行了更正:现在你会得到我正在得到的。(对此感到抱歉)
var n = i + 1;到
var n = i + 3;
编辑2: 另一件事,如果它溢出,为什么不引发异常?
添加: 发生溢出时,是不是设置的类型不对
变量n
在声明中 var n = i + 3;
相应地到另一种类型?
欢迎您提出更好的标题,因为这没有意义......至少我
谢谢
解决方案
更新:海报解决了他的问题。
1) 这是预期的输出,因为您向 int.MaxValue 添加了 3 导致溢出。默认情况下,在 .NET 中,这是未经检查的代码中的合法操作,可以环绕负值,但如果您添加 checked
代码周围的块会抛出一个 OverflowException
反而。
2) 声明变量的类型 var
是在编译时而不是运行时确定的。规则是两个 Int32 相加得到一个 Int32,而不是 UInt32、Int64 或其他东西。因此,即使在运行时您可以看到结果对于 Int32 来说太大,它仍然必须返回 Int32。
3)它没有转换为另一种类型。
其他提示
1) -2147483646 is bigger than -2,147,483,648
2) 2147483648 is out of range
3) int is an alias for Int32
1)
首先,变量中的值不是-2147483646,而是-2147483648。再次运行测试并检查结果。
int 没有理由不能保存值 -2147483646。它在 -2147483648..2147483647 范围内。
2)
编译器选择变量的数据类型作为表达式结果的类型。该表达式返回一个 int 值,即使编译器为变量选择更大的数据类型,该表达式仍然返回一个 int 并且您得到与结果相同的值。
溢出的是表达式中的操作,而不是结果分配给变量时发生溢出。
3)
它没有在任何地方转换。
- 这是一个溢出, ,您的号码转为负值
- 这不是编译器的工作,因为运行时的循环可能会导致同样的事情
int
是别名或System.Int32
它们在 .Net 中是等效的。
这是因为位表示
您使用 Int32,但 char (8 位)也是如此
第一位保存符号,然后后面的位保存数字
所以用 7 位可以表示 128 个数字 0111 1111
当你尝试第129次时, 1000 0001
, ,符号位被设置,因此计算机认为它是 -1
.NET 中的算术运算不会更改实际类型。
您从一个(32 位)整数开始,+3 不会改变它。
这也是为什么当你这样做时你会得到一个意想不到的整数:
int a = 2147483647;
double b = a / 4;
或者
int a = 2147483647;
var b = a / 4;
对于这个问题。
编辑:
也不例外,因为.NET 会溢出该数字。
溢出异常只会在赋值操作时发生,或者如 Mark 所解释的,当您设置生成异常的条件时。
通过使用十六进制符号,您可以使我们所有人更容易做到这一点。
并不是每个人都知道第八个梅森素数是 0x7FFFFFFF
只是在说'
如果你想抛出异常,写
abc = checked(i+3)
反而。这将检查是否有溢出。
另外,在 C# 中,默认设置是在溢出时不引发异常。但是您可以在项目属性的某个位置切换该选项。