Bitwise shifting array of char's

后端 未结 7 1582
谎友^
谎友^ 2020-12-03 17:41

I have got an array of chars that I\'m trying to bitwise shift right >>, then & with another array. I think I have got the wrong idea of

相关标签:
7条回答
  • 2020-12-03 18:17

    If you want to perform operations such as shifting / OR / XOR / AND / etc.. on arrays, you should perform it in a loop, you cannot perform it directly on the array.

    0 讨论(0)
  • 2020-12-03 18:18

    I know this is old topic but i was not satisfied with the answers available, here is something i wrote recently which allows you to specify the amount of bits you can shift by and also there is simple XOR encryption in it.

    //https://github.com/ashvin-bhuttoo/CryptoTest/blob/master/CryptoTest/Crypto.cpp
    //CRYPTO CONFIGURATION PARAMETERS
    #define BIT_SHIFT 3
    #define XOR_KEY 0x3C
    #define ENABLE_XOR_VARIANCE true
    ////////////////////////////////
    
    int get_rs_mask(int shift)
    {
        switch (shift)
        {
        case 0:
            return 0x00;
        case 1:
            return 0x01;
        case 2:
            return 0x03;
        case 3:
            return 0x07;
        case 4:
            return 0x0F;
        case 5:
            return 0x1F;
        case 6:
            return 0x3F;
        case 7:
            return 0x7F;
        default:
            throw "get_rs_mask -> Error, shift argument outside legal range 0-7";
        }
    }
    
    void shift_right(char* buf, int msg_len, int shift)
    {
        unsigned char tmp = 0x00, tmp2 = 0x00;
        for (int k = 0; k <= msg_len; k++)
        {
            if (k == 0)
            {
                tmp = buf[k];
                buf[k] >>= shift;
            }
            else
            {
                tmp2 = buf[k];
                buf[k] >>= shift;
                buf[k] |= ((tmp & get_rs_mask(shift)) << (8 - shift));
    
                if (k != msg_len)
                    tmp = tmp2;
            }
        }
    }
    
    int get_ls_mask(int shift)
    {
        switch (shift)
        {
        case 0:
            return 0x00;
        case 1:
            return 0x80;
        case 2:
            return 0xC0;
        case 3:
            return 0xE0;
        case 4:
            return 0xF0;
        case 5:
            return 0xF8;
        case 6:
            return 0xFC;
        case 7:
            return 0xFE;
        default:
            throw "get_ls_mask -> Error, shift argument outside legal range 0-7";
        }
    }
    
    void shift_left(char* buf, int msg_len, int shift)
    {
        char tmp = 0x00, tmp2 = 0x00;
        for (int k = msg_len; k >= 0; k--)
        {
            if (k == msg_len)
            {
                tmp = buf[k];
                buf[k] <<= shift;
            }
            else
            {
                tmp2 = buf[k];
                buf[k] <<= shift;
                buf[k] |= ((tmp & get_ls_mask(shift)) >> (8 - shift));
    
                tmp = tmp2;
            }
        }
    }
    
    void crypt(char* buf, int msg_len, bool decrypt = false)
    {
        if (!decrypt)
        {
            shift_right(buf, msg_len, BIT_SHIFT);
            for (int k = 0; k < msg_len; k++)
            {
                buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
            }
            buf[msg_len] = '\0';
        }
        else
        {
            for (int k = 0; k < msg_len; k++)
            {
                buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
            }
            shift_left(buf, (msg_len)-1, BIT_SHIFT);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 18:20
    /** Shift an array right.
     * @param ar The array to shift.
     * @param size The number of array elements.
     * @param shift The number of bits to shift.
     */
    void shift_right(unsigned char *ar, int size, int shift)
    {
        int carry = 0;                              // Clear the initial carry bit.
        while (shift--) {                           // For each bit to shift ...
            for (int i = size - 1; i >= 0; --i) {   // For each element of the array from high to low ...
                int next = (ar[i] & 1) ? 0x80 : 0;  // ... if the low bit is set, set the carry bit.
                ar[i] = carry | (ar[i] >> 1);       // Shift the element one bit left and addthe old carry.
                carry = next;                       // Remember the old carry for next time.
            }   
        }
    }   
    
    0 讨论(0)
  • 2020-12-03 18:22

    You can shift only members of that arrays, a char (or an int). You can't shift an entire array. Shifting my_array tries to perform a shift operation on an array type (or a pointer to char) which is impossible. Do this instead:

    for (i = 0; i < size; i++) {
      my_array[i] >>= 1;
    }
    

    Also you must be careful with chars because they are usually signed, and a char containing a negative value will bring '1' from the left instead of zeros. So you better use unsigned chars.

    EDIT: The code above is simplistic. If you intended to shift right the array as a whole, not just each byte on its own, then you need to "manually" copy each LSB to the MSB of the byte to its right. Take a loop at the answer of Richard Pennington.

    0 讨论(0)
  • 2020-12-03 18:30

    You have to shift and compare elementwise.

    for(i = 0; i < len; ++i)
        array[i] >>= 3;
    

    for example. If you want to move the bits shifted out of one element to the next, it's more complicated, say you're shifting right, then

    unsigned char bits1 = 0, bits2 = 0;
    for(i = len-1; i >= 0; --i) {
        bits2 = array[i] & 0x07;
        array[i] >>= 3;
        array[i] |= bits1 << 5;
        bits1 = bits2;
    }
    

    traversing the array in the other direction because you need the bits from the next higher slot.

    0 讨论(0)
  • 2020-12-03 18:36
    /**
     * shift a number of bits to the right
     *
     * @param   SRC         the array to shift
     * @param   len         the length of the array
     * @param   shift       the number of consecutive bits to shift
     *
    */
    static void shift_bits_right(uint8_t SRC[], uint16_t len, uint32_t shift) {
        uint32_t i = 0;
    
        uint8_t start = shift / 8;
        uint8_t rest = shift % 8;
        uint8_t previous = 0;
    
        for(i = 0; i < len; i++) {
            if(start <= i) {
                previous = SRC[i - start];
            }
            uint8_t value = (previous << (8 - rest)) | SRC[i + start] >> rest;
            SRC[i + start] = value;
        }
    }
    
    0 讨论(0)
提交回复
热议问题