【问题标题】:Why doesn't this overflow?为什么这不会溢出?
【发布时间】:2009-07-14 05:38:46
【问题描述】:

鉴于此代码:

int x = 20000;
int y = 20000;
int z = 40000;

// Why is it printing WTF? Isn't 40,000 > 32,767?
if ((x + y) == z) Console.WriteLine("WTF?");

知道一个 int 可以容纳 -32,768 到 +32,767。为什么这不会导致溢出?

【问题讨论】:

  • 32 位机器中的 int 在大多数情况下是 4 个字节。
  • 您是否尝试打印出“x+y”,然后打印出 z?也许它们都被存储为相同的负数。
  • C# 中的 int 是 32 位 总是
  • 哇8个人的回答基本一样,下面
  • 我希望所有比原来正确答案晚发帖的人都删除他们多余的答案...

标签: c# .net visual-studio int integer-overflow


【解决方案1】:

在 C# 中,int 类型映射到 Int32 类型,该类型始终为 32 位,有符号。

即使你使用short,它仍然不会溢出,因为short + short 默认返回int。如果你将这个 int 转换为 short - (short)(x + y) - 你会得到一个溢出的值。你不会得到一个例外。您可以使用checked 行为来获取异常:

using System;

namespace TestOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            short x = 20000;
            short y = 20000;
            short z;

            Console.WriteLine("Overflowing with default behavior...");
            z = (short)(x + y);
            Console.WriteLine("Okay! Value is {0}. Press any key to overflow " +
                "with 'checked' keyword.", z);
            Console.ReadKey(true);

            z = checked((short)(x + y));
        }
    }
}

您可以在 MSDN 上找到有关 checked(和 unchecked)的信息。它基本上归结为性能,因为检查溢出比忽略它要慢一点(这就是为什么默认行为通常是unchecked,但我敢打赌,在某些编译器/配置中,你会在第一次遇到异常z 分配。)

【讨论】:

  • +1 我只想在此处添加 Scoregraphic 的链接,以使其成为一个完整而出色的答案。
  • 感谢您的提示,我添加了一些指向 Int32、int 和 short 类型的链接 =)
【解决方案2】:

http://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx

类型:int 范围:-2,147,483,648 到 2,147,483,647

【讨论】:

  • 投反对票,因为答案不完整。请参阅描述检查算术的答案。
  • 关于原始问题的答案是完整的(为什么没有溢出)。所以在我看来,投反对票是错误的。但是,请对您喜欢的解决方案进行投票。
【解决方案3】:

虽然每个人都说 32 位机器上的“int”类型很可能是 2^32 是正确的,但您的方法有一个明显的缺陷。

假设 int 是 16 位的。您正在分配一个会溢出 z 的值,因此 z 本身就会溢出。当您计算 x+y 时,您也会溢出 int 类型,这两种情况很可能会溢出到相同的值,这意味着您无论如何都会达到相等(这可能取决于编译器,我不太确定是否x+y 将被提升)。

进行实验的正确方法是让 z 拥有比 x 和 y 更大的数据类型。例如(对不起,纯 C,我不是 C# 人。但希望它说明了方法。)

int x = INT_MAX;
int y = INT_MAX;
int sum = x + y;
long long z = INT_MAX+INT_MAX;
if(sum == z) 
 printf("Why didn't sum overflow?!\n");

比较 sum 和 z 很重要,因为比较 x+y 和 z 可能仍然很好,这取决于编译器如何处理提升。

【讨论】:

  • 伟大的 C 示例。我实际上是从一个 C 人的博客上得到这个的,但是在 C# 中询问它,因为它在 SO 上并且它给出了相同的结果。
【解决方案4】:

在 C# 中,一个 Int 是 4 个字节。所以它的最大值为 2^31 或 2,147,483,648。如果您想要一个 2 字节整数,请使用 short 而不是 int。

【讨论】:

    【解决方案5】:

    因为 .NET 中的 int 是 有符号的 32 位数,范围为 -2,147,483,648 到 2,147,483,647

    参考:http://msdn.microsoft.com/en-us/library/5kzh1b5w(VS.80).aspx

    【讨论】:

      【解决方案6】:

      因为 int 是 32 位的,所以可以保存高达 ±2GB 的值。

      【讨论】:

        【解决方案7】:

        一个 int 的大小是 4 字节,所以它至少可以容纳 2^31,大约是 20 亿。

        【讨论】:

          【解决方案8】:

          int 关键字映射到 .NET Framework Int32 type,它可以保存从 -2,147,483,648 到 2,147,483,647 范围内的整数。

          【讨论】:

            【解决方案9】:

            在 C# 中 int (System.Int32) 是 32 位的,可以愉快地存储这个值。

            【讨论】:

              【解决方案10】:

              您被要求将结果打印为“WTF?” .那么它应该如何显示其他值。

              Int 表示 int32,其范围是 –2147483648 到 2147483647 你得到 int16 的范围:–32768 到 32767

              这就是它没有抛出任何错误的原因

              【讨论】:

                【解决方案11】:

                首先,您的代码在 int 的范围内...但是,如果它不在范围内,那么它也不会抱怨...因为您在执行 X+Y 后永远不会将值分配回任何变量你的 if 检查...

                假设如果你在做 X * Y 那么它将被计算并且结果将是一个 long 值然后来自变量 Z 的值被取并提升为一个 long 然后两者将被比较......记住从下限基元到上限基元值是隐含的。

                int x = 200000; //In your code it was 20000
                int y = 200000; //In your code it was 20000
                int z = 40000;
                
                // Why is it printing WTF? Isn't 40,000 > 32,767?
                // Note: X + Y = 200000 and not < 32,767 
                // would pass compiler coz you are not assigning and values are compared as longs
                // And since it's not equals to 40,000 the WTF did not got printed
                if ((x + y) == z) Console.WriteLine("WTF?");     
                // And x * y >= z is true WTF MULTIPLY got printed
                if ((x * y) >= z) Console.WriteLine("WTF MULTIPLY?"); 
                // Compiler would fail since x can't hold 40,00,00,00,000
                x = x * y; 
                

                【讨论】:

                  【解决方案12】:

                  以上所有内容都是正确的,但是,重要的是要知道,如果您分配的数字大于 2^32,它将无法编译!

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-20
                    • 2014-12-20
                    • 2018-10-11
                    • 2011-12-07
                    相关资源
                    最近更新 更多