问题
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?
回答1:
You are probably right that this can be considered as a bug in the actual standard. The current draft addresses this problem:
If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a; otherwise, the behavior of both a/b and a%b is undefined.
回答2:
Looking at the assembly code generated by gcc (x is defined as -1 earlier in the assembly):
movl x, %ecx
movl $-2147483648, %eax
movl %eax, %edx
sarl $31, %edx
idivl %ecx
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:
Divides the contents of the double-word contained in the combined %edx:%eax registers by the value in the register or memory location specified.
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 returns 2147483648
. BOOM! That's one more then INT_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):
…the result of the / operator is the algebraic quotient with any fractional part discarded.88) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
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
回答3:
It's the CPU's fault.
回答4:
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.
回答5:
The result of the modulus operation with negative operands is left implementation-defined in C89, and defined in C99 by §6.5.5/6:
…the result of the
/
operator is the algebraic quotient with any fractional part discarded.88) If the quotienta/b
is representable, the expression(a/b)*b
+a%b
shall equala
.88) This is often called "truncation toward zero".
For a two's-complement representation, INT_MIN / -1
is equal to INT_MAX + 1
, so it's not representable as an int
without wrapping, and I guess the implementation elects to leave it explosive.
来源:https://stackoverflow.com/questions/5925045/does-int-min-1-produce-undefined-behavior