Mirando el código ensamblador generado por gcc (x se define como -1 anteriormente en el montaje):
movl x, %ecx
movl $-2147483648, %eax
movl %eax, %edx
sarl $31, %edx
idivl %ecx
La primera instrucción computacional, sarl
, a la derecha se desplaza -2147483648
31 bits. Esto da como resultado -1
que se pone en %edx
.
Siguiente idivl
se ejecuta. Esta es una operación firmada. Permítanme citar la descripción:
divide el contenido de la palabra doble contenida en los combinados% EDX: EAX registros% por el valor en el Registro de Localización o la memoria especificada.
Así que -1:-2147483648/-1
es la división que sucede. -1:-2147483648
interpretado como una palabra doble es igual a -2147483648
(en una máquina con dos complementos). Ahora -2147483648/-1
sucede que devuelve 2147483648
. ¡AUGE! Eso es uno más que INT_MAX
.
Sobre la pregunta ¿por qué? ¿Esto es un error en gcc o me falta alguna excepción especial que hace el estándar?
En el estándar C99 esto es UB implícita (§6.5.5/6):
... el resultado de la/operador es el cociente algebraico con cualquier parte discarded.88 fraccional) Si el cociente una/b es representable, la expresión (a/b) * b + a% b será igual a.
INT_MIN/-1
no se pueden representar, por lo tanto esto es UB.
En C89, sin embargo, el operador% es la implementación definida y si se trata de un error del compilador o no se puede debatir. El problema se enumera en gcc sin embargo: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30484
Tenga en cuenta que la variable global es evitar que gcc desde la optimización de la computación. –
¿Qué esperarías como resultado tratando de obtener el módulo de un número negativo? – joce
"Cuando a o n son negativos, esta definición ingenua se rompe y los lenguajes de programación difieren en cómo se definen estos valores". http://en.wikipedia.org/wiki/Modulo_operation – joce