Rotating bits of any integer in C
Pass a integer 2 to this function and then return a integer which is 4
x = 2;
x = rotateInt('L', x, 1);
(left shift the bits by 1)
Example: 00000010 -> rotate left by 1 -> 00000100
but if I pass this:
x = rotateInt('R', x, 3);
it will return 64, 01000000
Here i开发者_JS百科s the code, can someone correct the error... thanks
int rotateInt(char direction, unsigned int x, int y)
{
unsigned int mask = 0;
int num = 0, result = 0;
int i;
for (i = 0; i < y; i++)
{
if (direction == 'R')
{
if ((x & 1) == 1)
x = (x ^ 129);
else
x = x >> 1;
}
else if (direction == 'L')
{
if ((x & 128) == 1)
x = (x ^ 129);
else
x = x << 1;
}
}
result = (result ^ x);
return result;
}
So, I'll assume you know what right and left shifts are. And that you know the difference between arithmetic and logical shifts.
C only has arithmetic shifts. It doesn't do logical shifts, nor does it do rotates. okay I lied, C does logical shifts on unsigned ints.
A rotate does, well, exactly that: it's the same as a logical shift, except when you shift past the end of the number, the digits "wrap around" to the other side. For example
0010
right-rotated is 0001
. If you right-rotate again, you get 1000
. See, the 1
wrapped around, or rotated, to the other side of the integer.
The left rotate is similar: 0100
left rotate 1000
left rotate 0001
left rotate 0010
etc.
Note that rotates don't keep the sign bit as an arithmetic right-shift would.
So, C only has arithmetic shifts. So you have to implement the "rotate" part manually. So, take a left-rotate. You would want to:
- Capture the value of the left-most bit. (is it a 0 or 1?)
- Do a left-shift
- Set the right-most bit - which is the bit we talked about in step 1 (which needs to be rotated around) to the correct value, based on what we captured from step 1.
You should be able to figure out a similar method for right rotates.
good luck!
The accepted answer is very nice and straight-forward.
However, I was doing some K&R exercises to refresh my C, and wanted to share this rotate-to-the-right function which may come in handy for people trying to learn bit-wise operations.
unsigned int rightRotateBits(unsigned int inputWord, int numberOfBitsToRotate) {
int bitWidth = sizeof(inputWord) * 8;
// Rotating 32 bits on a 32-bit integer is the same as rotating 0 bits;
// 33 bits -> 1 bit; etc.
numberOfBitsToRotate = numberOfBitsToRotate % bitWidth;
unsigned int tempWord = inputWord;
// Rotate input to the right
inputWord = inputWord >> numberOfBitsToRotate;
// Build mask for carried over bits
tempWord = tempWord << (bitWidth - numberOfBitsToRotate);
return inputWord | tempWord;
}
For left-rotations just pass values between -1 and -31 to the bitAmount
argument.
Do note that this function favors teachability/legibility/simplicity over efficiency/portability/compactness.
Since no one told you how to implement this, you can use intrinsics, for visual studio they are _rotl, _rotl64, _rotr, _rotr64.
Oh, but rotation and shifts are 2 different things!
I was reading K&R, too, so this is a very straightforward rotate function for unsigned int:
unsigned int rightrot(unsigned int x, unsigned int n)
{
return (x >> n) | (x << (sizeof(int) * CHAR_BIT - n)); /* CHAR_BIT is defined in limits.h */
}
unsigned int leftrot(unsigned int x, unsigned int n)
{
return (x << n) | (x >> (sizeof(int) * CHAR_BIT - n));
}
Where n
is the number of bits to rotate.
Have a look at the bitwise shift operators:
http://en.wikipedia.org/wiki/Bitwise_operators#Shifts_in_C.2C_C.2B.2B_and_Java
It seems like your rotate to the right is RIGHT. 1 fell of the side and returned back again from the left?
Anyway, here are your ingredients:
http://tigcc.ticalc.org/doc/keywords.html#if - for determining if it is 'L' or 'R'
http://tigcc.ticalc.org/doc/keywords.html#for - for counting number of times to shift
and
http://msdn.microsoft.com/en-us/library/f96c63ed(VS.80).aspx - to actually shift it
Go, play with it. It WILL work eventually!
I recommend using an unsigned int
.
#define DIR_LEFT 0
#define DIR_RIGHT 1
unsigned int rotateInt(unsigned int in, int amount, byte dir)
{
return(dir == DIR_RIGHT ? (in >> amount) | ((in & ((0x01 << amount) - 1)) << (sizeof(unsigned int)*8 - amount)) : (in << amount) | ((in & ~((sizeof(unsigned int)*8*8 - 1) >> amount)));
}
精彩评论