2012-06-28 13 views
19

El resultado de abs (-2147483648) es -2147483648, ¿no es así? parece inaceptable.¿Por qué el valor absoluto del entero negativo máximo -2147483648 es todavía -2147483648?

printf("abs(-2147483648): %d\n", abs(-2147483648)); 

de salida:

abs(-2147483648): -2147483648 
+1

Creo que este es un comportamiento indefinido. No tengo el estándar C a mano, así que no puedo respaldarlo. –

+5

¿Qué esperas que sea, dado que 'abs (int)' devuelve un 'int'? –

+7

El último borrador de C11 dice (7.21.6.1, sobre abs y amigos) "Si el resultado no se puede representar, el comportamiento no está definido" –

Respuesta

18

La norma dice acerca abs():

Los abs, labs y llabs funciones computan el valor absoluto de un entero j. Si el resultado no se puede representar, el comportamiento no está definido.

Y el resultado de hecho no se puede representar porque la representación del complemento de 2 de enteros con signo no es simétrica. Piénselo ... Si tiene 32 bits en un int, eso le otorga 2 valores distintos de INT_MIN a INT_MAX. Esa es una cantidad par de valores. Entonces, si solo hay un 0, la cantidad de valores mayores que 0 no puede ser igual a la cantidad de valores menores que 0. Por lo tanto, no existe una contrapartida positiva para INT_MIN con un valor de - INT_MIN.

Entonces, lo que es inaceptable es llamar al abs(INT_MIN) en su plataforma.

-5

probar este

printf("abs(-2147483648): %u\n", abs(-2147483648)); 
+5

Esto, mi amigo, tiene un comportamiento indefinido. Está imprimiendo un entero con signo con el formateador sin firmar. I -1 porque además no responde la pregunta. –

10

Desde 2147483648 es mayor que INT_MAX en su aplicación, a continuación, abs(-2147483648) no está definido.

5

Este es el código en abs.c en el código fuente glibc de GNU.

/* Return the absolute value of I. */ 
int 
DEFUN(abs, (i), int i) 
{ 
    return(i < 0 ? -i : i); 
} 

Así, abs (-2147483648) return - (- 2147483648). En x86, es poner en práctica por esta instrucción de dos

movl $-2147483648, %eax 
negl %eax 

instrucción desd se lleva a cabo de esta manera: num = 0-num; sbb se implementa de esta manera: Resta la fuente del destino y resta 1 extra si está configurada la bandera de acarreo. Así que abs (-2147483648) (hex es 0x80000000) -> - (- 2147483648) -> 0 - (- 2147483648) se convierte (0x80000000) finalmente.

detalles de la instrucción desd, por favor visita http://zsmith.co/intel_n.html#neg

detalles de la instrucción SBB, visite http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

+0

Y? Quiero decir, ¿elaborarlo? –

9

Los números negativos suelen estar representados con un complemento binario.

Convertir positivo a negativo se utiliza lógica

x -> not(x)+1 

para 8 bits aritmética

01111111b es 127 y -127 se convierte
10000000b + 1 = 10000001b

y para dirección opuesta -127 10000001b se convierte en
01111110b + 1 = 01111111b

¿Qué hay de -128?

-128 es 10000000b y no hay una contrapartida positiva, porque no hay 128 en aritmética de 8 bits con signo.

10000000 -> + 1 = 01111111 10000000 y -128 nuevo

Lo mismo se aplica a la pregunta original

+0

por eso 0 y el valor mínimo son siempre los mismos después de negar en complemento a dos –

Cuestiones relacionadas