Best practices for circular shift (rotate) operations in C++

前端 未结 16 1558
情深已故
情深已故 2020-11-22 00:09

Left and right shift operators (<< and >>) are already available in C++. However, I couldn\'t find out how I could perform circular shift or rotate operations.

16条回答
  •  独厮守ぢ
    2020-11-22 00:39

    Below is a slightly improved version of Dídac Pérez's answer, with both directions implemented, along with a demo of these functions' usages using unsigned char and unsigned long long values. Several notes:

    1. The functions are inlined for compiler optimizations
    2. I used a cout << +value trick for tersely outputting an unsigned char numerically that I found here: https://stackoverflow.com/a/28414758/1599699
    3. I recommend using the explicit syntax for clarity and safety.
    4. I used unsigned char for the shiftNum parameter because of what I found in the Additional Details section here:

    The result of a shift operation is undefined if additive-expression is negative or if additive-expression is greater than or equal to the number of bits in the (promoted) shift-expression.

    Here's the code I'm using:

    #include 
    
    using namespace std;
    
    template 
    inline T rotateAndCarryLeft(T rotateMe, unsigned char shiftNum)
    {
        static const unsigned char TBitCount = sizeof(T) * 8U;
    
        return (rotateMe << shiftNum) | (rotateMe >> (TBitCount - shiftNum));
    }
    
    template 
    inline T rotateAndCarryRight(T rotateMe, unsigned char shiftNum)
    {
        static const unsigned char TBitCount = sizeof(T) * 8U;
    
        return (rotateMe >> shiftNum) | (rotateMe << (TBitCount - shiftNum));
    }
    
    void main()
    {
        //00010100 == (unsigned char)20U
        //00000101 == (unsigned char)5U == rotateAndCarryLeft(20U, 6U)
        //01010000 == (unsigned char)80U == rotateAndCarryRight(20U, 6U)
    
        cout << "unsigned char " << 20U << " rotated left by 6 bits == " << +rotateAndCarryLeft(20U, 6U) << "\n";
        cout << "unsigned char " << 20U << " rotated right by 6 bits == " << +rotateAndCarryRight(20U, 6U) << "\n";
    
        cout << "\n";
    
    
        for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned char) * 8U; ++shiftNum)
        {
            cout << "unsigned char " << 21U << " rotated left by " << +shiftNum << " bit(s) == " << +rotateAndCarryLeft(21U, shiftNum) << "\n";
        }
    
        cout << "\n";
    
        for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned char) * 8U; ++shiftNum)
        {
            cout << "unsigned char " << 21U << " rotated right by " << +shiftNum << " bit(s) == " << +rotateAndCarryRight(21U, shiftNum) << "\n";
        }
    
    
        cout << "\n";
    
        for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned long long) * 8U; ++shiftNum)
        {
            cout << "unsigned long long " << 3457347ULL << " rotated left by " << +shiftNum << " bit(s) == " << rotateAndCarryLeft(3457347ULL, shiftNum) << "\n";
        }
    
        cout << "\n";
    
        for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned long long) * 8U; ++shiftNum)
        {
            cout << "unsigned long long " << 3457347ULL << " rotated right by " << +shiftNum << " bit(s) == " << rotateAndCarryRight(3457347ULL, shiftNum) << "\n";
        }
    
        cout << "\n\n";
        system("pause");
    }
    

提交回复
热议问题