0

I was just wondering if there was a way to bit shift a number "in place"? I've googled exactly that, and I can't find anything that pertains to what I want to do. Say I have the number 0b01001101, and I want to shift it twice to the right "in place", appending any numbers that fall off to the beginning. So it would look like 0b01010011. Is there any function in c++ that would allow me to bit shift left or right like that?

Machavity
  • 30,841
  • 27
  • 92
  • 100
Polosky
  • 88
  • 5
  • 13
  • 4
    Is the term "circular shift" what you're looking for? http://stackoverflow.com/questions/776508/circular-shift-operations-in-c And also you can google that term – Yuf Jul 22 '11 at 17:05
  • Okay, how would I go about making my own? Should i just AND it with 1, if result is 1, shift right 1 and then OR it with 255 (or however large the binary is)? And similar method for left shift? – Polosky Jul 22 '11 at 17:07
  • @Yuf Yes, I think that is exactly what I was looking for! :D – Polosky Jul 22 '11 at 17:08
  • Look up "rotate with carry". Most processors have an instruction that performs this. – Thomas Matthews Jul 22 '11 at 19:46
  • To nitpick, the common difference between a shift and a rotate is that a rotate involves carry (from a previous operation). – Thomas Matthews Jul 22 '11 at 19:48

6 Answers6

1

Using the assembly instruction ror and getting the carry flag's value each time should do the work.

int rotate(int x, int n)
{
    for(int i = 0; i < n; i++) {
        __asm {
            ror   x, 1            ; rotate and store limit bit in cf
            lahf                  ; get part of flags in ah
            and   ah, 1           ; get only the cf
            shl   eax, 31         ; put it at the end
            and   x, eax          ; and store in x
        }
    }

    return x;
}
BlackBear
  • 22,411
  • 10
  • 48
  • 86
1

Write one yourself, I think it's not hard.

First store the right two bits,and then do the bit shift.Finally fill the left two bits with the stored bits.

moonkey
  • 311
  • 3
  • 13
1

You want to implement a rotational shift

Here's a templatized version that should work with all types of ints (including shorts, chars, ints, and unsigned/signed alike).

template<class T>
T rotate_shift_right(T x, int shift)
{
    if ((shift > 0) && (shift < (sizeof(x)*8)))
    {
        x = ((unsigned)x >> shift) | (x << (sizeof(x) * 8 - shift));
    }
    return x;
}

template<class T>
T rotate_shift_left(T x, int shift)
{
    if ((shift > 0) && (shift < (sizeof(x)*8)))
    {
        x = (x << shift) | (((unsigned)x) >> (sizeof(x) * 8 - shift));
    }
    return x;
}
selbie
  • 100,020
  • 15
  • 103
  • 173
0

I think shifting it and then anding the last byte onto the beginning should work.

Rocky Pulley
  • 22,531
  • 20
  • 68
  • 106
  • While this Q&A has seemingly run its course you should probably edit your answer to use "or'ing" as "anding" the last byte is the wrong operation. – tinman Jul 22 '11 at 17:31
0

No, you should create your custom one

Manlio
  • 10,768
  • 9
  • 50
  • 79
  • this is true, though minimalistic, and answers the question – ShinTakezou Jul 22 '11 at 17:15
  • This is really a comment, not an answer to the question. Please use "add comment" to leave feedback for the author. – TemplateRex Aug 09 '12 at 11:38
  • @rhalbersma well, if I read again the question I think my post is actually an answer. Maybe too short (guess that's why 2 downvotes) but is correct. – Manlio Aug 09 '12 at 13:39
  • @Saphrosit it is a "strict subsequence" of the accepted answer (because you don't specify how to write one), and doesn't add anything. If you self-delete, you regain your downvotes :-) – TemplateRex Aug 09 '12 at 13:41
0

This is implemented as vendor-specific extensions. For MSVC, you can use _rotl8, _rotl16 (or _rotr* for rotating to the right). Not sure about GCC, but you can always drop to assembly and use the rol or ror.

Blindy
  • 65,249
  • 10
  • 91
  • 131