Make sure your numbers are the correct size in memory. This C program works (and comes with a bit-printing function to help you debug/understand).
#include <stdio.h>
#include <stdlib.h>
uint32_t print_4_bits(uint32_t x){
int i,res;
for(i=0;i<4;i++){
printf("%u",(x&0x80000000)>>31);
x=x<<1;
}
return x;
}
void print_bits(uint32_t x){
int i;
for(i=0;i<8;i++){
x=print_4_bits(x);
printf(" ");
}
}
uint32_t rol32(uint32_t n, uint32_t d){
return (n<<d)|(n>>(32-d));
}
int main(){
uint32_t n = 0xa3519eba;
uint32_t expected=0xcf5d51a8;
uint32_t d = 0xf;
print_bits(n);
printf("\n");
print_bits(rol32(n,d));
printf("\n");
if(rol32(n,d)!=expected)printf("boo\n");
}
Here is the output:
1010 0011 0101 0001 1001 1110 1011 1010
1100 1111 0101 1101 0101 0001 1010 1000
A bit more explanation: Each data type takes a designated amount of space in memory, and ints can be of varying sizes. Furthermore you are bit-shifting what could potentially be negative numbers stored in two's complement notation, so the shifting may be filling with 1s, as explained in this post:
Right shifting negative numbers in C
You can solve both the memory size problem and the negative numbers problem by enforcing 32-bit unsigned integers. In C (and likely C++ too) that is with uint32_t
.
As for your actual bit-twiddle, say you have the number 0110 1100
and you rotate it by 2 bits, seeking 1011 0001
as a solution.
Start with
0110 1100
Shift left 2 places
1011 0000
<-right most bits filled with 0.
Shift right 8-2=6 places
0000 0001
<- left-most 6 filled with 0.
Now if you bitwise and them with |
you get the bits you cared about from each part of the solution (the ones you don't care about are parenthesised).
1011 00(00) | (0000 00)01 = 1011 0001