INT_MIN % -1 是否会产生未定义的行为?
gcc 生成浮动代码,为以下代码引发 SIGFPE
:
#include <limits.h>
int x = -1;
int main()
{
return INT_MIN % x;
}
但是,我在标准中找不到该代码调用未定义或实现定义的行为的声明。据我所知,它需要返回 0。这是 gcc 中的错误还是我错过了标准的一些特殊异常?
gcc generates floating code that raises SIGFPE
for the following code:
#include <limits.h>
int x = -1;
int main()
{
return INT_MIN % x;
}
However I can find no statement in the standard that this code invokes undefined or implementation-defined behavior. As far as I can tell, it's required to return 0. Is this a bug in gcc or am I missing some special exception the standard makes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可能是对的,这可以被视为实际标准中的错误。 当前草案解决了这个问题:
You are probably right that this can be considered as a bug in the actual standard. The current draft addresses this problem:
查看 gcc 生成的汇编代码(x 在汇编中前面定义为 -1):
第一个计算指令
sarl
右移-2147483648
31 位。这会导致-1
被放入%edx
中。接下来执行
idivl
。这是一个签名操作。我引用一下描述:所以
-1:-2147483648 / -1
是发生的除法。-1:-2147483648
解释为双字等于-2147483648
(在二进制补码机器上)。现在发生-2147483648 / -1
并返回2147483648
。繁荣!这比INT_MAX
还多一个。关于为什么问题,这是 gcc 中的错误还是我错过了标准的一些特殊例外?
在 C99 标准中,这是隐式的 UB (§6.5.5/6):
INT_MIN / -1
无法表示,因此这是 UB。然而,在 C89 中,% 运算符是实现定义的,这是否是编译器错误可以争论。不过,该问题已在 gcc 中列出: http://gcc.gnu.org/bugzilla /show_bug.cgi?id=30484
Looking at the assembly code generated by gcc (x is defined as -1 earlier in the assembly):
The first computational instruction,
sarl
, right shifts-2147483648
31 bits. This results in-1
which is put in%edx
.Next
idivl
is executed. This is a signed operation. Let me quote the description:So
-1:-2147483648 / -1
is the division that happens.-1:-2147483648
interpreted as a double word equals-2147483648
(on a two's complement machine). Now-2147483648 / -1
happens which returns2147483648
. BOOM! That's one more thenINT_MAX
.About the why question, is this a bug in gcc or am I missing some special exception the standard makes?
In the C99 standard this is implicit UB (§6.5.5/6):
INT_MIN / -1
cannot be represented, thus this is UB.In C89 however the % operator is implementation defined and whether this is a compiler bug or not can be debated. The issue is listed at gcc however: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30484
CPU 故障。
It's the CPU's fault.
此处作为缺陷报告提出了相同的问题
http:// /www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#614
不幸的是,我没有看到决议部分明确指出它应该产生 UB。除法确实会产生 UB,但对于
%
运算符来说并不明显。The same question is asked here as a Defect Report
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#614
Unfortunately I don't see it stated explicitly in the resolution part that it should produce UB. The division would indeed produce UB, but for the
%
operator it is not obvious.具有负操作数的模运算的结果在 C89 中由实现定义,并在 C99 中由 §6.5.5/6 定义:
对于补码表示,
INT_MIN / -1
等于INT_MAX + 1
,因此它不能在不换行的情况下表示为int
,并且我猜想实施选择让它具有爆炸性。The result of the modulus operation with negative operands is left implementation-defined in C89, and defined in C99 by §6.5.5/6:
For a two's-complement representation,
INT_MIN / -1
is equal toINT_MAX + 1
, so it's not representable as anint
without wrapping, and I guess the implementation elects to leave it explosive.