Rotação direita de bits em C
Estou trabalhando no exercício 2-8 em K&R, que nos pede para escrever uma função de rightrot(int x, int n)
forma que todos os bits de x
sejam deslocados n vezes para a direita, com os bits que caem da extremidade direita reaparecendo na extremidade esquerda.
Aqui está minha tentativa de solução em que eu mudo cada bit um por um:
int rightrot(int x, int n)
{
int i, rmb;
for(i = 0; i < n; ++i)
{
// get right-most bit
rmb = x & 1;
// shift 1 to right
x = x >> 1;
// if right-most bit is set, set left-most bit
if (rmb == 1)
x = x | (~0 ^ (~0 >> 1) );
}
return x;
}
Quando eu executar rightrot(122, 2)
, espero obter 94
desde 122
is 1111010
e 94
is 1011110
. Em vez disso, eu entendo o 30
que é 0011110
. Claramente, meu método para definir o bit mais à esquerda não está funcionando como eu esperava. Alguém identificou um erro óbvio? Estou apenas aprendendo a capturar bits e coisas do gênero.
NOTA: eu peguei a técnica para definir o bit mais à esquerda deste post.
Respostas
Vamos analisar (~0 ^ (~0 >> 1) )
:
~0
is -1
~0 >> 1
is novamente -1
, se o bit de sinal for 1
rightshift preencherá os novos bits com 1
s.
-1 ^ -1
é 0
.
x = x | 0
é x
.
A solução é que você deve usar tipos de dados não assinados se quiser fazer operações de bits.
Portanto, você deve usar a linha x = x | (~0u ^ (~0u >> 1) );
Para evitar outros problemas, o parâmetro x
também deve ser unsigned int
.
https://ideone.com/7zPTQk