Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C#规范保留(int.MinValue/-1)实现的定义?_C#_Language Design - Fatal编程技术网

为什么C#规范保留(int.MinValue/-1)实现的定义?

为什么C#规范保留(int.MinValue/-1)实现的定义?,c#,language-design,C#,Language Design,表达式int.Minvalue/-1根据C#规范产生实现定义的行为: 7.8.2除法操作员 如果左操作数是最小的可表示int或long值,而右操作数是–1,则 发生溢出。在选中的上下文中,这会导致 要抛出的System.ArtimeticException(或其子类)。在一个 未选中的上下文,它是实现定义的 抛出System.ArrithmeticException(或其子类)或 溢出未报告,结果值为 左操作数 测试程序: var x = int.MinValue; var y = -1; Co

表达式
int.Minvalue/-1
根据C#规范产生实现定义的行为:

7.8.2除法操作员

如果左操作数是最小的可表示int或long值,而右操作数是–1,则 发生溢出。在选中的上下文中,这会导致 要抛出的System.ArtimeticException(或其子类)。在一个 未选中的上下文,它是实现定义的 抛出System.ArrithmeticException(或其子类)或 溢出未报告,结果值为 左操作数

测试程序:

var x = int.MinValue;
var y = -1;
Console.WriteLine(unchecked(x / y));
这会在.NET 4.5 32位上抛出一个
OverflowException
,但它不必这样做

为什么规范没有定义结果实现?以下是反对这样做的理由:

  • 在这种情况下,x86
    idiv
    指令总是导致异常
  • 在其他平台上,可能需要运行时检查来模拟此情况。但与该部门的成本相比,该支票的成本将很低。整数除法非常昂贵(15-30个周期)
  • 这会带来兼容性风险(“一次写入无处运行”)
  • 开发人员感到惊讶
  • 另一个有趣的事实是,如果
    x/y
    是一个compiletime常量,我们确实会得到
    未选中(int.MinValue/-1)=int.MinValue

    Console.WriteLine(unchecked(int.MinValue / -1)); //-2147483648
    
    这意味着,
    x/y
    可以有不同的行为,这取决于所使用的语法形式(不仅取决于
    x
    y
    的值)。规范允许这样做,但这似乎是一个不明智的选择。为什么C#设计成这样


    A指出了规范中规定了这种确切行为的地方,但它没有(充分)回答为什么语言是这样设计的。备选方案没有讨论。

    C#的一个主要设计目标据说是“最小意外法则”。根据这条准则,编译器不应该试图猜测程序员的意图,而应该向程序员发出信号,说明需要额外的指导才能正确地指定意图。这适用于感兴趣的情况,因为在的限制范围内,该操作会产生非常令人惊讶的结果:Int32.MinValue/-1的计算结果为Int32.MinValue。发生溢出,需要不可用的第33位0才能正确表示Int32.MaxValue+1的正确值


    正如预期的那样,并在您的报价中指出,在选中的上下文中会引发异常,以提醒程序员未能正确指定意图。在未检查的上下文中,允许实现与检查的上下文中的行为相同,或者允许溢出并返回意外结果。有一些特定的上下文,例如位旋转,在这些上下文中,使用有符号的int是很方便的,但实际上需要溢出行为。通过检查实现说明,程序员可以确定这种行为是否真的如预期的那样。

    这是C语言规范的大哥公共语言基础设施规范的副作用。第三节第3.31章描述了DIV操作码的功能。一个C#spec经常不得不遵从的规范,是不可避免的。它指定它可以抛出,但不要求抛出

    否则,就需要对实际处理器的功能进行现实的评估。每个人都用的是奇怪的。英特尔处理器在溢出行为方面过于古怪,它们早在20世纪70年代就设计好了,当时假设每个人都会使用INTO指令。没人知道,改天再说吧。它不会忽略IDIV上的溢出,但是会引发“去陷阱”,不能忽略那响亮的爆炸声

    在处理器行为不一致的基础上编写语言规范和运行时规范非常困难。C#团队对此几乎无能为力,只是提出了不精确的语言。通过记录OverflowException而不是算术异常,他们已经超越了规范。非常淘气。他们偷看了一眼


    一眼就看出了这种做法。这不太可能是个问题,抖动决定是否内联。而抛出,期望的是内联版本也会这样做。还没有人感到失望。

    dimitry on的评论表明规范并非总是这样解读。@Henkholtman这个问题是关于语言设计的。建议的副本不能回答这个问题。(重提我自己的问题有点尴尬。)《傻瓜》的答案充分回答了为什么部分。当你认为你有一个更具体的问题时,你应该链接到原文并详细说明不同之处。@HenkHolterman现在会这样做。@HenkHolterman是的,他解释了我所知道的x86情况。但为什么要定义这个实现呢?我不反对抛出异常。我想知道为什么允许其他行为。取消除法可能很方便,但实际上在Microsoft.NET上并不存在。这是因为溢出仅在操作数为常量时发生。如果需要未经检查的溢出,则无法获得它。@usr编译器不是使用未经检查的溢出,而VB.Net默认使用已检查的溢出吗?另请参见@AndreasniederMir运行第一个代码段,它未选中并抛出。(第二个未选中,不会使用相同的输入抛出。)ECMA强制执行异常。这将为C#也授权它扫清道路。为什么他们允许非抛出的情况,尽管
    div
    从不溢出?它不允许,它只是说它可能抛出算术异常。CLI规范中的强制行为的措辞非常不同。你可以随便读,但你知道C团队是怎么读的:)上面写着