The program takes two numbers as input: num - a number for which a right cyclic shift must be performed byte by byte, and bytes - the number of bytes by which it must be shifted to the right.
The program works correctly only when shifting bytes for the value of 1. If asked to shift bytes for any other number, the output is not correct. What's wrong here?
unsigned long long shiftr(unsigned long long num, unsigned char bytes) {
unsigned long long mask;
switch (bytes)
{
case 1:
mask = 0xFF;
break;
case 2:
mask = 0xFFFF;
break;
case 3:
mask = 0xFFFFFF;
break;
case 4:
mask = 0xFFFFFFFF;
break;
case 5:
mask = 0xFFFFFFFFFF;
break;
case 6:
mask = 0xFFFFFFFFFFFF;
break;
case 7:
mask = 0xFFFFFFFFFFFFFF;
break;
case 8:
mask = 0xFFFFFFFFFFFFFFFF;
break;
default:;
}
num = mask & ( ((num & 0x1) << (bytes * 8 - 1)) | (num >> 1) );
return num;
}
With the value num
= 1, the shift is performed correctly in all cases. But if you enter another number, the program will not work correctly. Why is that?
The expression used in this assignment statement
num = mask & ( ((num & 0x1) << (bytes * 8 - 1)) | (num >> 1) );
is wrong. For example this sub-expression (num & 0x1)
extract only the first bit of the number that is shifted to the left while this sub-expression (num >> 1)
moves the number to the right only by one bit.
Also you need to check the value of the parameter bytes
that is not greater than 8.
Pay attention to that the parameter bytes
specifies the number of bytes to shift not bits.
Using your approach the function can look the following way as shown in the demonstration program below.
#include <iostream>
unsigned long long shiftr( unsigned long long num, unsigned char bytes )
{
const size_t N = sizeof( num );
bytes %= N;
if ( bytes != 0 )
{
unsigned long long mask;
switch (bytes)
{
case 1:
mask = 0xFF;
break;
case 2:
mask = 0xFFFF;
break;
case 3:
mask = 0xFFFFFF;
break;
case 4:
mask = 0xFFFFFFFF;
break;
case 5:
mask = 0xFFFFFFFFFF;
break;
case 6:
mask = 0xFFFFFFFFFFFF;
break;
case 7:
mask = 0xFFFFFFFFFFFFFF;
break;
}
num = ( mask & num ) << 8 * ( N - bytes ) | num >> 8 * bytes;
}
return num;
}
int main()
{
unsigned long long num = 0x123456789ABCDEF0;
for (unsigned char bytes = 0; bytes < 8; ++bytes)
{
std::cout << std::hex << num << ": " << shiftr( num, bytes ) << '\n';
}
}
The program output is
123456789abcdef0: 123456789abcdef0
123456789abcdef0: f0123456789abcde
123456789abcdef0: def0123456789abc
123456789abcdef0: bcdef0123456789a
123456789abcdef0: 9abcdef012345678
123456789abcdef0: 789abcdef0123456
123456789abcdef0: 56789abcdef01234
123456789abcdef0: 3456789abcdef012