int、uint或者什么?

3
考虑以下内容。
        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的值?(int范围为-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的类型为其他类型是否正确?


如果这个标题不让人感到困惑,欢迎您提出更好的建议。

谢谢

8个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
7

更新: 发布者修正了他的问题。

1) 这个输出是预期的,因为你将3添加到int.MaxValue中导致溢出。在.NET中,默认情况下,在未经检查的代码中,这是一个合法的操作,会对负值进行包装,但如果你在代码周围添加一个checked块,它将抛出一个OverflowException异常。

2) 用var声明的变量的类型是在编译时确定的,而不是运行时。这是一个规则,即两个Int32相加得到的是Int32,而不是UInt32、Int64或其他什么类型。所以即使在运行时你可以看到结果对于Int32来说太大了,它仍然必须返回一个Int32。

3) 它没有转换成另一种类型。


3

1)
首先,变量中的值不是-2147483646,而是-2147483648。请再次运行测试并检查结果。

int类型可以容纳-2147483646的值,因为它在范围-2147483648..2147483647之内。

2)
编译器选择变量的数据类型是表达式结果的类型。该表达式返回int值,即使编译器会选择一个更大的数据类型来存储变量,表达式仍然返回int,结果相同。

溢出发生在表达式中的操作,而不是当结果被赋给变量时发生的。

3)
它没有在任何地方进行转换。


+1 是因为你是第一个真正考虑var的人,我认为这才是 OP 的真正问题。 var并不意味着“找出在这里使用最合适的类型”。它只是字面意思是“我懒得弄清楚你的输入类型,所以请帮我做到”。这并不意味着使用var是不好的,但如果你想正确使用它,你需要理解它的作用。 - Michael Madsen

3
 1)  -2147483646 is bigger than -2,147,483,648
 2) 2147483648 is out of range
 3) int is an alias for Int32

1
  1. 这是一个溢出, 你的数字被包裹并变成了负数
  2. 这不是编译器的工作,因为运行时的循环也会导致同样的问题
  3. intSystem.Int32 的别名,在 .Net 中它们是等效的。

1
这是因为位表示的原因。你使用的是Int32,但对于char(8位)也是一样的。 第一个位表示符号,然后后面的位表示数字。 所以用7位可以表示128个数字0111 1111。 当你尝试第129个数字1000 0001时,符号位被设置,计算机会认为它是-1。

0

如果您使用十六进制表示法,这将使我们所有人的工作更加轻松。

并不是每个人都知道第八个梅森素数是0x7FFFFFFF。

只是说一下而已。


0

.NET 中的算术运算不会改变实际类型。
你从一个(32位)整数开始,+3 不会改变它。

这也是为什么当你这样做时会得到一个意外的整数:

int a = 2147483647;
double b = a / 4;

或者

int a = 2147483647;
var b = a / 4;

就这个问题而言。

编辑:
没有例外,因为.NET会溢出数字。
溢出异常只会在赋值操作或者像Mark解释的那样设置条件以生成异常时才会发生。


0
如果您想抛出异常,请编写以下代码:

abc = checked(i+3)

可以使用“checked”关键字来检查溢出,而不是使用“unchecked”。

此外,在C#中,默认设置是不会在发生溢出时抛出异常的。但是你可以在项目属性中的某个地方切换该选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,