Reversing bits and converting binary to decimal in C - c

I'm building a function that, given an integer, reverses all 32 of its bits (including sign bit), converts that into a new integer, and returns it. I've almost finished it but I've run into two problems:
Part 1:
If I give it test(15); then
buffer = 11110000000000000000000000000000, which is indeed 15 with all the bits reversed.
but if I give it test(-15); then
buffer = 10001111111111111111111111111111, which is NOT right, it should be 10001000000000000000000000000001 (the 1 at the end is the sign bit). So for negative values, building my buffer string is going awry. Should I just change it to a positive integer, reverse the bits, and change the bit at the end to 1? Or is there some easier way of building this string?
Part 2:
"answer", the integer I'm returning that is supposed to represent these numbers, is never accurate. If I give it test(1500) answer = 185, when it should be 1000341504. What's the best way to turn a 32-bit binary number into an integer?
my code:
int test(int var){
printf("reversing %d:\n", var);
char buffer[32];
int i = 0;
int power = sizeof(var) * 8;
int answer = 0;
while(power > 0){
//check the lowest bit and put a 0 or 1 into the array
if((var & 1) == 1){
buffer[i] = '1';
i++;
}
else{
buffer[i] = '0';
i++;
}
//shift to the next bit
var>>= 1;
power--;
}
i++;
buffer[i] = '\0';
printf("\nbuffer = %s", buffer);
//loop through the array in reverse, building the number
while(i > 0){
if(buffer[i] == '0'){
i--;
}
else{
answer += (2 ^ (32 - i)); //here is where I try to add up answer
i--;
}
}
printf("\nanswer = %d \n\n\n\n", answer);
return 0;
}

The incorrect part of your conversion is:
answer += (2 ^ (32 - i))
2 ^ (32 - i)) is 2 XOR (32 - i), because ^ is the XOR-operator.
I'd do the conversion like this:
unsigned int answer = 0, pow=1;
for(int i = sizeof(buffer) - 1; i >= 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
By doing it backwards (from 31 to 0), you don't have to use pow or create a
function that does 2 to the power of i. That would give you the integer value
of your binary interpretation, always positive. If you want to the integer value
of a 2-complement binary:
int answer = 0;
unsigned int pow=1;
for(int i = sizeof(buffer) - 1; i > 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
if(buffer[0] == '1')
answer |= 0x80000000; // setting last bit
Or the more general solution (doesn't care if answer is signed or unsigned)
int answer = 0; // or unsigned int answer = 0;
size_t len = strlen(buffer);
for(int i = len - 1; i > 0; --i)
{
if(buffer[i] == '1')
answer |= 1 << len - 1 - i;
}
edit
I also found an error on your conversion to string:
char buffer[32];
...
i++;
buffer[i] = '\0';
The buffer hold 32 chars, one for each bit. There is no room left for the
0-terminating byte there, also with i++ you are overflowing the buffer, i
would be 33, so you are overflowing by 2.
If you are not going to treat buffer as a string (no strcpy, no strcmp,
no printf), then you don't have to store the terminating '\0'. Remove the
buffer[i] = '\0'; and that's it.
However you do print it as a string, so you would have to declare buffer as
char buffer[33];
and remove the i++ before buffer[i] = '\0';.
In that case, you would need to change the for loops as well, to
for(i = sizeof(buffer) - 2; i >= 0; --i)
and
for(i = sizeof(buffer) - 2; i > 0; --i)
or strlen(buffer) - 1 instead of sizeof(buffer) - 2 (in case you do the
convertion on another function and you pass the pointer to buffer.

Related

int to bitstring function to handle negative numbers

How would I change this function to handle negative numbers? It correctly outputs everything but it does not make the leading bit 1 when negative. I can't do a negative check then simply force the first bit to be 1 because the amount of 0s between the leading bit and rest of the numbers will be off.
char* fromInt(int bin){
static char str[33];
str[1] = '\0';
int n;
for (n = 128; n > 0; n >>= 1){
if( (bin & n) == n){
strcat(str, "1");
}else{
strcat(str, "0");
}
}
return str;
}
I guess what you want is:
char* fromInt(int bin)
{
static char str[33];
str[0] = '0' + ((bin & 0x80000000) == 0x80000000);
str[1] = '\0';
for (int n = 0x40000000; n > 0; n >>= 1) {
if ((bin & n) == n)
strcat(str, "1");
else
strcat(str, "0");
}
return str;
}
The function has two steps. First is to determine the setting of sign bit (assuming that int object has 32 bits and it uses two's complement arithmetic):
(bin & 0x80000000) == 0x80000000
yields either 1 or 0. Because it's about the sign, It might have been written simply as:
'0' + (bin < 0)
The second step is to loop over remaining bits from position 30 to 0, like in the original code.
Here is an example program:
int main(void)
{
printf("%s\n", fromInt(0));
printf("%s\n", fromInt(1536));
printf("%s\n", fromInt(-1));
return 0;
}
This will output:
00000000000000000000000000000000
00000000000000000000011000000000
11111111111111111111111111111111

Error in Program to implement cyclic redundancy check

I have tried to implement crc in c.My logic is not very good.What I have tried is to copy the message(msg) in a temp variable and at the end I have appended number of zeros 1 less than the number of bits in crc's divisor div.
for ex:
msg=11010011101100
div=1011
then temp becomes:
temp=11010011101100000
div= 10110000000000000
finding xor of temp and div and storing it in temp
gives temp=01100011101100000 counting number of zeros appearing before the first '1' of temp and shifting the characters of div right to that number and then repeating the same process until decimal value of temp becomes less than decimal value of div. Which gives the remainder.
My problem is when I append zeros at the end of temp it stores 0's along with some special characters like this:
temp=11010011101100000$#UFI#->Jp#|
and when I debugged I got error
Floating point:Stack Underflow
here is my code:
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
void main() {
char msg[100],div[100],temp[100];
int i,j=0,k=0,l=0,msglen,divlen,newdivlen,ct=0,divdec=0,tempdec=0;
printf("Enter the message\n");
gets(msg);
printf("\nEnter the divisor\n");
gets(div);
msglen=strlen(msg);
divlen=strlen(div);
newdivlen=msglen+divlen-1;
strcpy(temp,msg);
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
for(i=divlen;i<newdivlen;i++)
div[i]='0';
printf("\nModified div:");
printf("%s",div);
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,j++);
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,k++);
while(tempdec>divdec)
{
for(i=0;i<newdivlen;i++)
{
temp[i]=(temp[i]==div[i])?'0':'1';
while(temp[i]!='1')
ct++;
}
for(i=newdivlen+ct;i>ct;i--)
div[i]=div[i-ct];
for(i=0;i<ct;i++)
div[i]='0';
tempdec=0;
for(i=newdivlen;i>0;i--)
tempdec=tempdec+temp[i]*pow(2,l++);
}
printf("%s",temp);
getch();
}
and this part of the code :
for(i=newdivlen;i>0;i--)
divdec=divdec+div[i]*pow(2,i);
gives error Floating Point:Stack Underflow
The problem is that you wrote a 0 over the NUL terminator, and didn't put another NUL terminator on the string. So printf gets confused and prints garbage. Which is to say that this code
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
printf("\nModified Temp:");
printf("%s",temp);
should be
for(i=msglen;i<newdivlen;i++)
temp[i]='0';
temp[i] = '\0'; // <--- NUL terminate the string
printf("\nModified Temp:");
printf("%s",temp);
You have to do this with integers
int CRC(unsigned int n);
int CRC_fast(unsigned int n);
void printbinary(unsigned int n);
unsigned int msb(register unsigned int n);
int main()
{
char buf[5];
strcpy(buf, "ABCD");
//convert string to number,
//this is like 1234 = 1*1000 + 2*100 + 3*10 + 4, but with hexadecimal
unsigned int n = buf[3] * 0x1000000 + buf[2] * 0x10000 + buf[1] * 0x100 + buf[3];
/*
- "ABCD" becomes just a number
- Any string of text can become a sequence of numbers
- you can work directly with numbers and bits
- shift the bits left and right using '<<' and '>>' operator
- use bitwise operators & | ^
- use basic math with numbers
*/
//finding CRC, from Wikipedia example:
n = 13548; // 11010011101100 in binary (14 bits long), 13548 in decimal
//padding by 3 bits: left shift by 3 bits:
n <<= 3; //11010011101100000 (now it's 17 bits long)
//17 is "sort of" the length of integer, can be obtained from 1 + most significant bit of n
int m = msb(n) + 1;
printf("len(%d) = %d\n", n, m);
int divisor = 11; //1011 in binary (4 bits)
divisor <<= (17 - 4);
//lets see the bits:
printbinary(n);
printbinary(divisor);
unsigned int result = n ^ divisor;// XOR operator
printbinary(result);
//put this in function:
n = CRC(13548);
n = CRC_fast(13548);
return 0;
}
void printbinary(unsigned int n)
{
char buf[33];
memset(buf, 0, 33);
unsigned int mask = 1 << 31;
//result in binary: 1 followed by 31 zero
for (int i = 0; i < 32; i++)
{
buf[i] = (n & mask) ? '1' : '0';
//shift the mask by 1 bit to the right
mask >>= 1;
/*
mask will be shifted like this:
100000... first
010000... second
001000... third
*/
}
printf("%s\n", buf);
}
//find most significant bit
unsigned int msb(register unsigned int n)
{
unsigned i = 0;
while (n >>= 1)
i++;
return i;
}
int CRC(unsigned int n)
{
printf("\nCRC(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
divisor = polynomial << shift;
printbinary(n);
printbinary(divisor);
printf("-------------------------------\n");
n ^= divisor;
printbinary(n);
printf("\n");
}
printf("result: %d\n\n", n);
return n;
}
int CRC_fast(unsigned int n)
{
printf("\nCRC_fast(%d)\n", n);
unsigned int polynomial = 11;
unsigned int plen = msb(polynomial);
unsigned int divisor;
n <<= 3;
for (;;)
{
int shift = msb(n) - plen;
if (shift < 0) break;
n ^= (polynomial << shift);
}
printf("result: %d\n\n", n);
return n;
}
Previous problems with string method:
This is infinite loop:
while (temp[i] != '1')
{
ct++;
}
Previous problems with string method:
This one is too confusing:
for (i = newdivlen + ct; i > ct; i--)
div[i] = div[i - ct];
I don't know what ct is. The for loops are all going backward, this makes the code faster sometimes (maybe 1 nanosecond faster), but it makes it very confusing.
There is another while loop,
while (tempdec > divdec)
{
//...
}
This may go on forever if you don't get the expected result. It makes it very hard to debug the code.

Converting negative binary to decimal

I have been trying for the past several hours to convert a negative binary with the first bit as 1 to a decimal. The twos complement conversion seems to be impossible but I believe there has to be some easier way to do this because this is just the beginning of a beginner class in C.
int power;
int count = 0;
int length = strlen(value);
int result = 0;
int negResult = 0;
int i = length - 1;
int j;
if (value[0] == '1') {
for (; i >= 0; i--) {
if (value[i] == '1')
result += 1;
result << 1;
}
printf("%d\n", result);
result = ~result;
result += 1;
printf("%d\n", result);
for (j = 8; j > 0; j--) {
if (result << (8-j) == 1) {
power = (int) pow(2,count);
negResult += power;
}
count++;
}
printf("-%d\n", negResult);
}
else {
for (; i >= 0; i--) {
if (value[i] == '1') {
power = (int) pow(2,count);
result = result + power;
}
count++;
}
printf("%d\n", result);
}
}
I pass it:
binary_to_decimal("10011011");
and I get 5 then -5 and then -0 for each printf.
I did not include the code that actually converts it to a decimal since for positive binaries it works fine and I believe once the twos complement works it should work for negative binaries as well.
You may not be clear about what temp += '0' is doing. It's not making a string, rather it's offsetting an uninitialized pointer and is the cause of the segfault when you come to actually use it as in temp2[j]. To work with strings like I think you're wanting to, check out strcat().
I would junk this and start over. Don't manipulate chars in strings, just convert the string to a binary. Write some code to walk the input string from the first character towards the last. Keep a result integer for your answer, initially 0. As you walk through the string, shift result << 1, and then if you see a char '1', add a number 1 to result. If you see a '0' in the string don't add anything, but in either case do the left shift first.
This will get you a binary of however many bits you have. For negative numbers (topmost (first) bit = '1') you will need to sign extend by OR-ing '1' into all the bits above the sign bit, bitwise-invert the result and add 1. Check this on paper to see how it works, and be aware the input string can't be too long. Good luck with the class.
int length = strlen(value);
unsigned int result = 0;
unsigned int signExtend;
unsigned int negResult = 0;
// assemble incoming chars as bits in an unsigned int
for (int i=0;i<length;i++) {
result = result << 1;
if (value[i] == '1')
result += 1;
}
printf("0x%x, %d\n", result, result); // see it is a hex number and a decimal
// if negative, convert to positive number
if (value[0] == '1') {
// first, sign-extend
signExtend = (1 << (length-1));
signExtend -= 1;
signExtend = ~signExtend;
result |= signExtend;
printf("signExtend mask = 0x%x, sign-extended number = %x\n", signExtend, result);
// then, two's complement
negResult = ~result;
negResult += 1;
// show the result with the '-' sign explicitly added:
printf("result is -%d\n", negResult);
// but actually, once you have sign extended,
// you can cast the result as signed and just print it:
printf("result as signed int = %d\n", (int)result);
} else {
// positive result, just print it
printf("result is %d\n", result);
}
here's how I would do it
int btd(char *str)
{
int i , l = strlen(str) , neg = 0;
int res = 0;
for(i = 0 ; i < l ; i++)
{
if(!i)
{
if(str[i] == '1');
neg++;
continue;
}
if(str[i] == '1')
{
res <<= 1;
res |= 1;
}
else
res <<= 1;
}
if(neg)
res *= -1;
return res;
}

masking most significant bit

I wrote this function to remove the most significant bit in every byte. But this function doesn't seem to be working the way I wanted it to be.
The output file size is always '0', I don't understand why nothing's been written to the output file. Is there a better and simple way to remove the most significant bit in every byte??
In relation to shift operators, section 6.5.7 of the C standard says:
If the value of the right operand is negative or is greater than or
equal to the width of the promoted left operand, the behavior is
undefined.
So firstly, remove nBuffer << 8;. Even if it were well defined, it wouldn't be an assignment operator.
As people have mentioned, you'd be better off using CHAR_BIT than 8. I'm pretty sure, instead of 0x7f you mean UCHAR_MAX >> 1 and instead of 7 you meant CHAR_BIT - 1.
Let's just focus on nBuffer and bit_count, here. I shall comment out anything that doesn't use either of these.
bit_count += 7;
if (bit_count == 7*8)
{
*out_buf++ = nBuffer;
/*if((write(out_fd, bit_buf, sizeof(char))) == -1)
oops("Cannot write on the file", "");*/
nBuffer << 8;
bit_count -= 8;
}
nBuffer = 0;
bit_count = 0;
At the end of this code, what is the value of nBuffer? What about bit_count? What impact would that have on your second loop? while (bit_count > 0)
Now let's focus on the commented out code:
if((write(out_fd, bit_buf, sizeof(char))) == -1)
oops("Cannot write on the file", "");
Where are you assigning a value to bit_buf? Using an uninitialised variable is undefined behaviour.
Instead of going through all of the bits to find the high one, this goes through only the 1 bits. high() returns the high bit of the argument, or zero if the argument is zero.
inline int high(int n)
{
int k;
do {
k = n ^ (n - 1);
n &= ~k;
} while (n);
return (k + 1) >> 1;
}
inline int drop_high(int n)
{
return n ^ high(n);
}
unsigned char remove_most_significant_bit(unsigned char b)
{
int bit;
for(bit = 0; bit < 8; bit++)
{
unsigned char mask = (0x80 >> bit);
if( mask & b) return b & ~mask;
}
return b;
}
void remove_most_significant_bit_from_buffer(unsigned char* b, int length)
{
int i;
for(i=0; i<length;i++)
{
b[i] = remove_most_significant_bit(b[i]);
}
}
void test_it()
{
unsigned char data[8];
int i;
for(i = 0; i < 8; i++)
{
data[i] = (1 << i) + i;
}
for(i = 0; i < 8; i++)
{
printf("%d\r\n", data[i]);
}
remove_most_significant_bit_from_buffer(data, 8);
for(i = 0; i < 8; i++)
{
printf("%d\r\n", data[i]);
}
}
I won't go through your entire answer to provide your reworked code, but removing the most significant bit is easy. This comes from the fact that the most significant bit can easily be found by using log base 2 converted to an integer.
#include <stdio.h>
#include <math.h>
int RemoveMSB(int a)
{
return a ^ (1 << (int)log2(a));
}
int main(int argc, char const *argv[])
{
int a = 4387;
printf("MSB of %d is %d\n", a, (int)log2(a));
a = RemoveMSB(a);
printf("MSB of %d is %d\n", a, (int)log2(a));
return 0;
}
Output:
MSB of 4387 is 12
MSB of 291 is 8
As such, 4387 in binary is 1000100100011 with a most significant bit at 12.
Likewise, 291 in binary is 0000100100011 with a most significant bit at 8.

Bitwise shifting array of char's

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 how to do this.
I thought, even though it was an array of chars just stating my_array >>= 1 would shift everything but I am getting an error: "error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"
The bitwise comparision I am trying to do is with a similar size array initiated to all "0's"...for that I'm getting: "error: invalid operands to binary & (have ‘char *’ and ‘char *’)"
Do I need to convert these array's into something else before I can shift and compare?
Sorry, I was not super clear... All great advice up to this point and I think I am realizing more that there is no super easy way to do this. More specifically, what I am trying to do is shift the bits of the WHOLE char array right 1, adding the bit shifted off the right back to the left most side of the array, do the bitwise compare with another array of same size.
Technically the compare doesn't have to be array with array... I just need the bits. Would it be easier to convert the array's to something else before trying to do the shifts/comparisons?
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.
You'll have to shift the entries in the array one by one. (And if you want to compare two of these, you'll need to do it element by element.)
If you were hoping that bits shifted off each char would get shifted into the next one, you'll need to take care of that manually too.
If you are wanting that shift-into-the-next-byte behaviour, and don't mind making your code nasty and nonportable and bug-prone, you might be able to take a pointer to the array, cast it to something like unsigned long long *, dereference it and shift the resulting integer, and store it back again.
BUT if that's the behaviour you want then you should be using an integer instead of a char[8] to begin with.
(If you could say more about what you're actually aiming to achieve, then more helpful answers may be possible.)
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.
/** 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.
}
}
}
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.
/**
* 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;
}
}
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);
}
}
/**
* Shift a number of bits to the right
*
* #param array The array to shift
* #param len The length of the array
* #param shift The number of consecutive bits to shift. To the right if shift is positif.
*
*/
static void shift_bits_right(uint8_t *array, int len, int shift) {
uint8_t macro_shift = shift / 8;
shift = shift % 8;
uint8_t array_out[len];
memset(array_out, 0, len);
for(int i = 0; i < len; i++) {
if(i+macro_shift < len)
array_out[i+macro_shift] += array[i]>>shift;
if(i+macro_shift+1 < len)
array_out[i+macro_shift+1] += array[i]<<(8-shift);
}
memcpy(array, array_out, len);
}
For everyone who is looking for a code snippet to (logically) shift right a byte array that actually works:
template<size_t N> void shift_right(array<uint8_t, N>& arr, uint64_t bits)
{
int64_t num_bytes = bits / 8;
int64_t num_bits = bits % 8;
for(int64_t i = N-1; i >= 0; i--)
{
int64_t i_from = i - num_bytes;
int64_t i_from_minus_one = i - num_bytes - 1;
uint8_t v_from = i_from < 0 ? 0 : arr[i_from];
uint8_t v_from_minus_one = i_from_minus_one < 0 ? 0 : arr[i_from_minus_one];
arr[i] = v_from >> num_bits | v_from_minus_one << (8 - num_bits);
}
}

Resources