除以零:未定义的行为或实现在C和/或C ++中定义?

关于除零,标准说:

C99 6.5.5p5 – /运算符的结果是第一个操作数除以第二个操作数的商; %运算符的结果是余数。 在这两个操作中,如果第二个操作数的值为零,则行为未定义。

C ++ 03 5.6.4 – 二进制/运算符产生商,而二进制%运算符产生第一个表达式除以第二个表达式的余数。 如果/或%的第二个操作数为零,则行为未定义。

如果我们将上述段落视为面值,则答案显然是两种语言的未定义行为 。 但是,如果我们进一步了解C99标准,我们会看到以下段落似乎是矛盾的(1):

C99 7.12p4 – 宏INFINITY扩展为float类型的常量表达式,表示正无穷大或无符号无穷大(如果可用);

标准是否有某种黄金法则 ,其中未定义的行为不能被(可能)矛盾的陈述所取代? 除此之外,我认为如果你的实现定义了INFINITY宏,那么除以零被定义为这样是不合理的。 但是,如果您的实现没有定义这样的宏,则行为是Undefined。

我很好奇这两种语言对于这个问题的共识是什么(如果有的话)。 如果我们谈论整数除法int i = 1 / 0 1/0与浮点除法float i = 1.0 / 0.0 ,答案是否会改变?

注意(1) C ++ 03标准讨论了包含INFINITY宏的库。

我没有看到任何矛盾。 除以零是未定义的,期间。 在引用文本中的任何地方都没有提到“……除非定义了INFINITY”

请注意,在数学中没有定义1/0 = 无穷大 。 有人可能会这样解释,但这是一种个人的“捷径”式解释,而不是一个合理的事实。

1/0不仅是无穷大

  lim 1 / x =∞(x  - > +0) 

为什么会这样?

这在数学上没有意义,它不像在数学中一般将1 / x定义为∞。 此外,您至少还需要两种情况:-1 / x和0 / x也不能等于∞。

一般来说, 除以零 ,有关计算机算术的部分。

我只获得了C99选秀权。 在§7.12/ 4中它说:

  INFINITY 

扩展为float类型的常量表达式,表示正或无符号无穷大(如果可用); 否则为float类型的正常量,在转换时溢出。

注意, INFINITY可以根据浮点溢出来定义,不一定是除零。

对于INFINITY宏:在IEEE754标准中有一个显式编码来表示+/-无穷大,即如果所有指数位都被置位且所有分数位被清除(如果设置了一个分数位,它代表NaN)

使用我的编译器, (int) INFINITY == -2147483648 ,因此如果返回INFINITIY,则计算结果为int i = 1/0的表达式肯定会产生错误的结果

这不是一个数学最纯粹的问题,而是一个C / C ++问题。

  • 根据所有现代C编译器/ FPU使用的IEEE 754标准,我们有
    • 3.0 / 0.0 = INF
    • 0.0 / 0.0 = NaN
    • -3.0 / 0.0 = -INF

FPU将有一个状态标志,如果需要,您可以将其设置为生成exception,但这不是常态。

当INF是有用的结果时,INF对于避免分支非常有用。 见这里的讨论

http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

底线,C99(根据你的引言)在“实现定义”的上下文中没有说明任何关于INFINITY的内容。 其次,你所引用的并没有表现出“未定义行为”的不一致含义。


[引用维基百科的未定义行为页面]“在C和C ++中,还使用了实现定义的行为,其中语言标准没有指定行为, 但实现必须选择行为并且需要记录和遵守它所选择的规则。”

更确切地说,标准意味着“实现定义”(我认为只是)当它使用那些关于语句的词时,因为“实现定义”是标准的特定属性。 C99 7.12p4的引用没有提到“实现定义”。

[来自C99标准(迟到的草案)]“未定义的行为:使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对其施加任何要求”

请注意,对于未定义的行为,“没有要求”!

[C99 ..]“实现定义的行为:未指定的行为,其中每个实现记录了如何做出选择”

[C99 ..]“未指明的行为:使用未指定的值,或本国际标准提供两种或更多种可能性的其他行为,并且不对其进行任何进一步的要求”

文档是实现定义行为的必要条件。

定义__STDC_IEC_559__实现需要遵守附件F中给出的要求,后者又要求浮点语义符合IEC 60559.标准对未定义的实现上的浮点除法行为没有要求__STDC_IEC_559__ ,但对于那些确定它的人来说。 在IEC 60559指定行为但C标准不指定行为的情况下,C标准要求定义__STDC_IEC_559__的编译器按照IEC标准中的描述进行操作。

根据IEC 60559(或美国标准IEEE-754)的定义,0为零的除法产生NaN,将浮点数除以正零或字典常数0,得到一个与被除数相同符号的INF值,除法一个浮点数由负零产生一个符号相反的INF。