Shift N bits an entire array of chars

倖福魔咒の 提交于 2020-01-07 05:38:26

问题


Let's say I have an array of chars and I want to shift N bits to the left each byte, carrying to the left, so only the N bits of the first character would be lost.

Example: kxmo shifted 3 bits to the left should become X@hx

This is what I have currently, but it's not working as expected:

#include <stdio.h>

int main(void) {
    //shift the array with length *len* *shift* bits to the left
    int len = 4, shift = 3;
    unsigned char a[len] = "kxmo";
    unsigned char b[len]; //X@hx

    unsigned char tmp = 0, tmp2 = 0;
    for(int i = len - 1; i > 0; i--) {
        tmp = 0 | (a[i] << shift);
        b[i] = a[i];

        tmp2 = 0 | (a[i - 1] << shift);
        b[i - 1] = (a[i - 1] << shift) ^ tmp;
    }

    printf("old: %s | new: %s\n", a, b);

    return 0;
}

Where am I failing?

Edit:

This is what I'm getting right now: old: kxmo | new: �xmo


回答1:


First, imagine doing it with pencil and paper. Let's say you are shifting two bytes by three bits, you start with bytes abcdefgh, ijklmnop, and you want to finish with defghijk, lmnop000.

In order to do this, you need to extract 00000ijk from the second byte, and OR it into the first byte after the shift. In order to do this, you need to shift the second byte by 8-shift to the right, and mask the result with 00000111 i.e. the last shift bits set to 1. This mask can be constructed by shifting 1 to the left shift+1 times, yielding 00001000, and subtracting 1 from the result.

Here is how you can do it:

char b1 = 'k';
char b2 = 'x';
int shift = 3;
int carry = 0, nextCarry;

nextCarry = (b1 >> (8-shift)) & ((1<<(shift+1))-1);
b1 <<= shift;
b1 |= carry;
carry = nextCarry;

Now do the same with b2:

nextCarry = (b2 >> (8-shift)) & ((1<<(shift+1))-1);
b2 <<= shift;
b2 |= carry;
carry = nextCarry;

If you do this in a loop, you would achieve the desired result.

Demo.




回答2:


How about something like that (assuming 0 <= shift < 8):

#define BITS_IN_BYTE 8
for(int i = len - 1; i > 0; i--) 
{
    b[i] = a[i] << shift;
    b[i - 1] = (a[i - 1] << shift) | (a[i] >> (BITS_IN_BYTE - shift));
}

I didn't check it but I hope it will do what you want.

EDIT

OK, I checked and it does what you expect.

NOTE --> you need to set len to 5 and not to 4 for '\0'. also note that the first iteration (b[i] = a[i] << shift;) will be done on the '\0' but since its value is 0, it is OK.



来源:https://stackoverflow.com/questions/32412281/shift-n-bits-an-entire-array-of-chars

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!