Pergunta

Eu tenho o código C em que eu faça o seguinte.

int nPosVal = +0xFFFF;   // + Added for ease of understanding
int nNegVal = -0xFFFF;   // - Added for valid reason

Agora, quando eu tento

printf ("%d %d", nPosVal >> 1, nNegVal >> 1);

I get

32767 -32768

É este esperado?

Eu sou capaz de pensar algo como

65535 >> 1 = (int) 32767.5 = 32767
-65535 >> 1 = (int) -32767.5 = -32768

Isto é, -32767,5 é arredondado para -32768.

É este o entendimento correto?

Foi útil?

Solução

Parece que a sua implementação é, provavelmente, fazer uma mudança bit aritmética com dois números de complemento. Neste sistema, se desloca todos os bits para a direita e, em seguida, preenche os bits superiores com uma cópia de tudo o que o último pedaço era. Então, por seu exemplo, tratando int como 32-bits aqui:

nPosVal = 00000000000000001111111111111111
nNegVal = 11111111111111110000000000000001

Após a mudança, você tem:

nPosVal = 00000000000000000111111111111111
nNegVal = 11111111111111111000000000000000

Se você converter isso de volta para decimal, você obtém 32767 e -32768 respectivamente.

Com efeito, um direito rodadas mudança no sentido de infinito negativo.

Editar: De acordo com a Seção 6.5.7 do mais recente projecto padrão, esse comportamento em números negativos é dependente de implementação:

O resultado da E1 >> E2 é E1-deslocada para a direita E2 mordeu posições. Se E1 tem um tipo não assinado ou se E1 tem um tipo assinado e um valor não negativo, o valor do resultado é parte integrante do quociente de E1 / 2 E2 . Se E1 tem um tipo assinado e um valor negativo, o valor resultante é definido pela implementação.

O racional declarou para isso:

a Comissão C89 afirmou a liberdade na implementação concedida pela K & R em não exigir a operação de deslocamento para a direita assinado a assinar prolongar, uma vez que tal exigência pode retardar o código rápido e uma vez que a utilidade de turnos sinal estendido é marginal. (Mudando complemento um negativo de dois de integer aritmeticamente direito um lugar é não o mesmo que dividir por dois!)

Assim dependente, em teoria, de implementação. Na prática, eu nunca vi uma implementação não fazer um certo deslocamento aritmético quando o operando esquerdo é assinado.

Outras dicas

Não, você não obter números fracionários como 0,5 quando se trabalha com números inteiros. Os resultados podem ser facilmente explicado quando você olha para as representações binárias dos dois números:

      65535: 00000000000000001111111111111111
     -65535: 11111111111111110000000000000001

Bit deslocando para o bit um direito, e estendendo-se à esquerda (nota que este é dependente de implementação, graças Trent):

 65535 >> 1: 00000000000000000111111111111111
-65535 >> 1: 11111111111111111000000000000000

converter de volta para decimal:

 65535 >> 1 = 32767
-65535 >> 1 = -32768

A especificação C não especifica se o bit de sinal é deslocado ao longo ou não. É dependente de implementação.

Quando você shift direita, o menos significativo-bit é descartado.

0xFFFF = 0 1111 1111 1111 1111, que certas turnos para dar 0 0111 1111 1111 1111 = 0x7FFF

-0xFFFF = 1 0000 0000 0000 0001 (2s complementar), que certas turnos para 1 1000 0000 0000 0000 = -0x8000

A-1: ??Sim. 0xffff >> 1 é 0x7fff ou 32767. Eu não tenho certeza do que -0xffff faz. Isso é peculiar.

A-2: A mudança não é a mesma coisa que se dividir. É pouco deslocando-a operação binária primitivo. Que às vezes pode ser usado para alguns tipos de divisão é conveniente, mas não é sempre o mesmo.

Sob o nível C, máquinas têm um núcleo de CPU que é inteiramente inteiro ou escalar . Embora estes dias a cada CPU desktop tem uma FPU, este não era sempre o hoje incorporado sistemas de casos e até mesmo são feitas sem instruções de ponto flutuante.

paradigmas de programação e design de CPU e línguas de hoje datam da época em que o FPU pode até não existir.

Assim, instruções da CPU implementar operações de ponto fixo , geralmente tratada como puramente inteira ops. Só se um programa declara itens de flutuador ou duplo existirão quaisquer frações. (Bem, você pode usar os ops CPU para "ponto fixo" com frações, mas que agora é e sempre foi bastante raro.)

Independentemente do que foi requerido por uma língua anos Standard Committee atrás, todas as máquinas razoáveis ??propagar o bit de sinal em turnos direito de números assinados. turnos direito de valores sem mudar em zeros à esquerda. Os bits deslocados para fora à direita são descartados no chão.

Para continuar a sua compreensão que você vai precisar para investigar "dois complementos aritmética".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top