按位移位char的数组

时间:2012-04-28 21:19:33

标签: c bit-manipulation

我有一个字符数组,我正在尝试向右移位>>,然后用另一个数组移位&。我想我对如何做到这一点有错误的想法。

我想,即使是一系列字符,只是陈述my_array >>= 1会改变一切,但我收到错误:"error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"

我要做的按位比较是使用类似大小的数组启动所有“0”...为此我得到:"error: invalid operands to binary & (have ‘char *’ and ‘char *’)"

在转换和比较之前,我是否需要将这些数组转换为其他数组?

对不起,我不是很清楚......到目前为止所有很好的建议,我想我更多地意识到没有超级简单的方法可以做到这一点。更具体地说,我要做的是将WHOLE字符数组的位右移1,将右移的位移回数组的最左侧,与另一个相同大小的数组进行逐位比较。 / p>

从技术上讲,比较不必是带数组的数组......我只需要这些位。在尝试进行转换/比较之前,将数组转换为其他内容会更容易吗?

7 个答案:

答案 0 :(得分:13)

你必须移位并比较元素。

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

。如果你想将从一个元素移出的位移动到下一个元素,那就更复杂了,比如你向右移,然后

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;
}

在另一个方向上遍历数组,因为你需要下一个更高位的位。

答案 1 :(得分:3)

/** 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.
        }   
    }
}   

答案 2 :(得分:2)

您必须逐个移动数组中的条目。 (如果你想比较其中的两个,你需要逐个元素地进行。)

如果你希望每个字符都移位,那么每个字符都会转移到下一个字符,你也需要手动处理它。

如果您想要转换到下一个字节的行为,并且不介意使您的代码变得令人讨厌且不可移植且容易出错,那么您可能可以获取指向该数组的指针,将其转换为像unsigned long long *这样的东西,取消引用它并移动生成的整数,然后再将它存储起来。

但如果这是您想要的行为,那么您应该使用整数而不是char[8]来开始。

(如果您可以详细说明您实际想要达到的目标,那么可能会有更多有用的答案。)

答案 3 :(得分:2)

如果你想在数组上执行诸如移位/ OR / XOR / AND /等等的操作,你应该在循环中执行它,你不能直接在数组上执行它。

答案 4 :(得分:2)

您只能移动该数组的成员,char(或int)。你无法移动整个阵列。移位my_array尝试对数组类型(或指向char的指针)执行移位操作,这是不可能的。这样做:

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

此外,您必须小心使用字符,因为它们通常是签名的,而包含负值的字符将从左侧带来“1”而不是零。所以你最好使用无符号字符。

修改 上面的代码很简单。如果您打算将数组作为一个整体向右移动,而不仅仅是每个字节本身,那么您需要“手动”将每个LSB复制到其右侧字节的MSB。回答理查德·彭宁顿的回答。

答案 5 :(得分:1)

我知道这是一个老话题,但是我对可用的答案不满意,这是我最近写的东西,它允许您指定可以移位的位数,并且其中还包含简单的XOR加密。

//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);
    }
}

答案 6 :(得分:0)

/**
 * 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;
    }
}