Question

So I have a binary representation of a number as a character array. What I need to do is shift this representation to the right by 11 bits.

For example,

I have a char array which is currently storing this string: 11000000111001 After performing a bitwise shift, I will get 110 with some zeros before it.

I tried using this function but it gave me strange output:

char *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.
    }
}
return ar;
}

Any help on this would be very much appreciated; let me know if I'm not being clear.

Was it helpful?

Solution

They are just characters...

char *shift_right(unsigned char *ar, int size, int shift)
   {

   memmove(&ar[shift], ar, size-shift);
   memset(ar, '0', shift);

   return(ar);
   };

Or, convert the string to a long-long, shift it, then back to a string:

char *shift_right(char *ar, int size, int shift)
   {
   unsigned long long x;
   char *cp;

   x=strtoull(ar, &cp, 2);  // As suggested by 'Don't You Worry Child'
   x = x >> shift;
   while(cp > ar)
      {
      --cp;
      *cp = (1 & x) ? '1' : '0';
      x = x >> 1;
      }

   return(ar);
   };

OTHER TIPS

If you really want to use bitwise shifting, then you can't do it on a string. Simply not Possible!!

You have to convert it to integer (use strtol for that) then do bitwise shifting. After that, convert it back to string (no standard library function for that, use for loop).

I would advise to keep the code simple and readable.

#include <stdio.h>
#include <stdlib.h>

void shift_right (char* dest, const char* source, int shift_n)
{
  uint16_t val = strtoul(source, NULL, 2);
  val >>= shift_n;

  for(uint8_t i=0; i<16; i++)
  {
    if(val & 0x8000) // first item of the string is the MSB
    {
      dest[i] = '1';
    }
    else
    {
      dest[i] = '0';
    }
    val <<= 1;    // keep evaluating the number from MSB and down
  }

  dest[16] = '\0';
}


int main()
{
  const char str [16+1] = "0011000000111001";
  char str_shifted [16+1];

  puts(str);
  shift_right(str_shifted, str, 11);
  puts(str_shifted);

  return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top