2011-03-29 13 views
9

En este código de abajoalmacenar números negativos

int main() 
{ 
int a = -1; 
printf("%d",a>>1); 
return 0; 
} 

¿Por qué se está dando salida -1.

+1

Consulte esta pregunta [operador de desplazamiento en C] (http://stackoverflow.com/questions/7622/shift-operator-in-c). – Mat

Respuesta

12

el desplazamiento de bit se define solo en los tipos sin signo, para los tipos con signo está definido por la implementación. Y esto es un refinamiento útiles por R ..

Estrictamente hablando, se define por tipos firmados cuando el valor es positivo y el resultado no desbordamiento y desplazamiento a la derecha es definida por la aplicación valores negativos . desplazamiento a la izquierda, por el contrario, no está definida para valores negativos

┌───┬──────────────┬──────────────────────────────────┬────────────────────────┐ 
│ │ Unsigned  │ Signed, positive     │ Signed, negative  │ 
├───┼──────────────┼──────────────────────────────────┼────────────────────────┤ 
│<< │ well-defined │ well-defined, except on overflow │ undefined behaviour │ 
│>> │ well-defined │ well-defined      │ implementation-defined │ 
└───┴──────────────┴──────────────────────────────────┴────────────────────────┘ 
+4

Estrictamente hablando, se define para tipos con signo siempre que el valor sea positivo y el resultado no se desborde, y el desplazamiento a la derecha sea definido por la implementación para valores negativos. El desplazamiento a la izquierda, por otro lado, está * indefinido * para los valores negativos. –

+1

Creo que sería "definido por la implementación" en C99 de acuerdo con [Wikipedia: Cambio aritmético] (http: //en.wikipedia.org/wiki/Arithmetic_shift) – Mat

5

Debido a -1 es 1111111 ... 111 en binario. a>>1 operación "extenderá" signo el bit de signo, por lo que obtiene 1111111 ... 111 de nuevo.

+0

Esto es solo en código complementario, que no es necesariamente la forma en que se representan los números. Pero aún así, en muchas plataformas tiene razón –

+0

@Arment - De acuerdo, definitivamente depende de la máquina. Debería haberlo señalado. Claramente, sin embargo, firmar extender es lo que está sucediendo en este caso particular. –

+0

@Armen - No sé si recibiste comentarios previos. (Disculpe, escriba su nombre.) –

1

La mayoría de los compiladores eligen interpretar >> en números con signo para ser desplazamiento aritmético. Por lo tanto, dado que el número es inicialmente negativo (es decir, el bit MSB es 1), después de un desplazamiento a la derecha, ese bit se reemplaza por otro 1 para conservar el signo, por lo que termina con -1 cuando comenzó.

0

El operador >> en un valor con signo puede realizar un desplazamiento aritmético o lógico, según el compilador. Los cambios aritméticos retienen el bit de signo, por lo que -1 (que en una máquina complementaria de 2 s, que en estos días es prácticamente la única variedad que encontrará) seguirá siendo -1 cuando se desplaza a la derecha. (Tenga en cuenta que el estándar C explícitamente no especifica si >> en un número firmado es un cambio aritmético o lógico. Sin embargo, siempre es un cambio lógico en números sin signo)

0

La definición de cambio de bit en valores con signo es depende de la implementación. Compruebe los documentos de su compilador para saber cómo lo maneja.

0

En memoria número entero con signo almacenado como complemento 2 si sign int y cuando se leen datos de la memoria {% d} se convierte a formato original así que aquí 2 complemento de -1 se almacenará en memoria, digamos entero tomar 2 bytes 2's complement of -1 is 1111 1111 1111 1111

Después de realizar a>>1 se va a cambiar 0111 1111 1111 1111 ahora como sabemos que cuando se leen los datos de la memoria se convierte de nuevo a 0 complemento a fin de tomar el complemento de 0111 1111 1111 1111 de 2 será como 1000 0000 0000 0001 que es igual a -1

Nota: Complemento 2 de +ve número es el mismo que el complemento de representación binaria original 2 es solo para -ve número. En C número siempre almacenado como complemento de 2 forma

+1

Primero, los números sin firmar no se almacenan como complemento a 2. Para números con signo, no todas las arquitecturas/implementaciones del compilador también usan el complemento 2. C estándar permite cualquier otra codificación numérica aunque es casi imposible encontrar un complemento de 1 o una implementación de magnitud de signo actualmente –

+0

@ LưuVĩnhPhúc: por qué su salida es -1 si no está firmado no está almacenado como complemento 2 #include void main() { unsigned int a = -1; printf ("% d", a); } –

+0

los números sin firmar se imprimen por '% u', obtendrá un comportamiento indefinido –

Cuestiones relacionadas