Thread: bitwise char array shift

  1. #1
    Registered User
    Join Date
    Dec 2017
    Posts
    15

    bitwise char array shift

    Hi,

    This code shif left on array bitwse, but dŽont work whel.

    Same body say me whre is the probem?

    0000000 0000000 11111111
    after 10 shifts

    00000011 11111100 00000000



    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    void imprime(unsigned char texto);
    void shift_right(unsigned char *ar, int size, int shift, unsigned char valent);
    void shift_4bits_left(unsigned char* array, int size,int shift);
    int main()
    {
    unsigned char alfabeto[8] ={0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000010, 0b00000000, 0b0000001};
    int a,b;
    unsigned char Shift_data=1;
    shift_right(&alfabeto[0], 8, 2,1);
    
    
      //imprime array
    for (a=0; a<8; a++)
    {
      imprime(alfabeto[a]);
    }
      return 0;
    }
    
    void shift_right(unsigned char *ar, int size, int shift, unsigned char valent)
    {
       unsigned short carry = 0;
        while (shift--) {
            for (int k = size-1 ; k >= 0; --k) {
                unsigned short next = (ar[k]<<1) & 0x80;
                ar[k] =  (ar[k] << 1) | carry ;
    
                carry = next;
            }
        }
    }
    
    void imprime(unsigned char texto)
    {
      int i;
      for (i = 0; i < 8; i++) {
          printf("%d", !!((texto << i) & 0x80));
      }
      printf("\n");
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Code:
    #include <stdio.h>
     
    typedef unsigned char byte;
     
    void shift_right(byte *ar, int size, int shift) {
        int carry = 0;
        while (shift-- > 0)
            for (int k = size; k-- > 0; ) {
                int nextCarry = ar[k] & 0x80;  // you need to save the carry before you shift it
                ar[k] = (ar[k] << 1) | carry;
                carry = nextCarry;
            }
    }
     
    void imprime(byte texto) {
        for (int i = 0; i < 8; i++)
            putchar('0' + !!((texto << i) & 0x80));
        putchar('\n');
    }
     
    int main() {
        byte alfabeto[8] = {
            0b00000000, 0b00000000, 0b00000000, 0b00000000,
            0b00000000, 0b00000010, 0b00000000, 0b00000010
        };
     
        shift_right(alfabeto, 8, 2);
     
        for (int i = 0; i < 8; i++)
            imprime(alfabeto[i]);
     
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    15
    Thanks for your quikly help.

    ...00000011 11111100 00000000
    ...byte 2 <- byte 1 <- byte 0 shift from lower byte to upper byte

    In need to shift left from byte 0 to byte 8 , bitwise.

    I tested your code with yor changes but dĂČnt work whell.

    I know, in the byte alfabeto[]{0 byte, 1 byte, 2 byte....... ok

    Thanks

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Code:
    #include <stdio.h>
     
    typedef unsigned char byte;
     
    void shift_left(byte *a, int size, int shift) {
        while (shift--) {
            int carry = 0;
            for (int i = size; i-- > 0; ) {
                int nextCarry = a[i] & 0x80;   // actually stores 0b10000000
                a[i] = (a[i] << 1) | !!carry;  // carry needs to be added in as 0b00000001, not 0b10000000
                carry = nextCarry;
            }
        }
    }
     
    void print_bits(byte b) {
        for (int i = 0; i < 8; i++)
            putchar('0' + !!((b << i) & 0x80));
        putchar('\n');
    }
     
    int main() {
        byte a[8] = {
            0b00000000, 0b00000000, 0b00000000, 0b00000000,
            0b00000000, 0b00000000, 0b00000000, 0b11111111
        };
     
        shift_left(a, 8, 10);
     
        for (int i = 0; i < 8; i++)
            print_bits(a[i]);
     
        return 0;
    }
    BTW, it seems to be a left shift, not a right shift.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    15

    Smile

    Hi, again

    Now work fine, but shift from hight byte to lower byte.



    [CODE]
    byte a[8] = {0b00000111 byte0, 0b00000000byte1, 0b00000000byte2, 0b00000000....,0b00000000...., 0b00000000..., 0b00000000..., 0b00000000...};

    shift left mean shift from byte0 to byte n..

    The definicion of array is "byte a[8] = {0b00000111 byte0, byte

    Yor last option shift byte high to low. it mean shift right. iŽm wrong?



    Yor first option is ok for my project, bat do not work whel. the shift direction is ok, but the cary do not whork whwell .


    Can you please check and verific yor first code for me and post it?


    thanks for yor patience




    This code please (check for me)
    Code:
    #include <stdio.h>
     
    typedef unsigned char byte;
     
    void shift_right(byte *ar, int size, int shift) {
        int carry = 0;
        while (shift-- > 0)
            for (int k = size; k-- > 0; ) {
                int nextCarry = ar[k] & 0x80;  // you need to save the carry before you shift it
                ar[k] = (ar[k] << 1) | carry;
                carry = nextCarry;
            }
    }
     
    void imprime(byte texto) {
        for (int i = 0; i < 8; i++)
            putchar('0' + !!((texto << i) & 0x80));
        putchar('\n');
    }
     
    int main() {
        byte alfabeto[8] = {
            0b00111111, 0b00000000, 0b00000000, 0b00000000,
            0b00000000, 0b00000000, 0b00000000, 0b00000000
        };
     
        shift_right(alfabeto, 8, 2);
     
        for (int i = 0; i < 8; i++)
            imprime(alfabeto[i]);
     
        return 0;
    }

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    You are missing the !! that I added before carry (line 10 in your code). Alternatively you could make it (carry >> 7). Look at my last post.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    Registered User
    Join Date
    Dec 2017
    Posts
    15
    Ok but im talking about your first code.
    Yor first code d ont have the !!.
    Remember your second code work fine and shift right. Is ok.
    But for my propose i need shift left. Like yor first code. Yor first code work but dont cary byte 0 to byte 2......
    So I ask you if you teste yor firt code and fix the cary error.
    Now im not able to test uni code. Just tomorrow morning i can test.

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by totoco View Post
    Ok but im talking about your first code.
    Yor first code d ont have the !!.
    Remember your second code work fine and shift right. Is ok.
    But for my propose i need shift left. Like yor first code. Yor first code work but dont cary byte 0 to byte 2......
    So I ask you if you teste yor firt code and fix the cary error.
    Now im not able to test uni code. Just tomorrow morning i can test.
    Seeing your code I assume you speak portuguese, right? I am brazillian and here's one article I wrote sometime ago:

    Deslocando uma string de bits.

    Maybe you adapt this to your needs.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by totoco View Post
    Thanks for your quikly help.

    ...00000011 11111100 00000000
    ...byte 2 <- byte 1 <- byte 0 shift from lower byte to upper byte

    In need to shift left from byte 0 to byte 8 , bitwise.
    As a technical note, if you shift left normally the leftmost bits will be discarded. If you somehow shift these bits back into the lower end, that describes a rotation.

    The method you have seen can be used to do this. If you copy the leftmost bit and or it to the rightmost place that does the rotation.

    And frankly there is no reason to work one bit at a time. Copy n bits with an appropriate mask and then or them to the low end.

    Code:
    #include <stdio.h>
    #include <limits.h>
    
    #define MSB_MASK 0x80U
    #define NBYTES 3
    
    typedef unsigned char ubyte;
    
    void rotateleft (ubyte *arr, int size, int shifts);
    void print (ubyte *arr, int size);
    
    int main (void)
    {
        ubyte bits[NBYTES] = {0x4FU, 0x0U, 0xFFU};
        puts("before: ");
        print(bits, NBYTES);
        puts("After rotating left 10 times:");
        rotateleft(bits, NBYTES, 10);
        print(bits, NBYTES);
        return 0;
    }
    
    void rotateleft (ubyte *arr, int size, int shifts)
    {    
        ubyte lomask; 
        ubyte himask; 
        int i;
        ubyte carry;
        
        if (shifts <= 0) /* no work */
            return;
        
        /* Any n bit shifts that is a multiple of CHAR_BIT is n *byte* shifts. If we do those first,
           we can bit shift by any remainder and have the correct answer.
        */
        if (shifts / CHAR_BIT > 0)
        {
            int byteshifts = shifts / CHAR_BIT;
            while (byteshifts-- > 0)
            {
                ubyte hold = arr[0];
                int i;
                for (i = 0; i < size - 1; i++) 
                {
                    arr[i] = arr[i + 1];
                }
                arr[size - 1] = hold;
            }
            shifts %= CHAR_BIT;
        }
            
        if (shifts == 0) /* no work */
            return;
        
        /*
           lowmask has the number of bits toggled that we want to shift. 
           himask takes these bits and shifts them to the high end of the byte. 
           Other than for creating himask, lowmask IS NOT used. 
        */
        lomask = (shifts > 1)? (1 << (shifts + 1)) - 1 : 1;
        himask = lomask << (CHAR_BIT - shifts);
        
        /* By copying the high end of the current byte we can shift, then OR it into 
           the low end of the next byte. Since we work on the last byte first, we copy the 
           first byte's high bits, and OR them into the last byte. 
        */
        carry = (arr[0] & himask) >> (CHAR_BIT - shifts);
        for (i = size - 1; i >= 0; i--)
        {
            ubyte nextCarry = (arr[i] & himask) >> (CHAR_BIT - shifts);
            arr[i] = (arr[i] << shifts) | carry;
            carry = nextCarry;
        }
    }
    
    void print(ubyte *arr, int size)
    {
        int i;
        ubyte mask;
        for (i = 0; i < size; i++)
        {
            for (mask = MSB_MASK; mask > 0; mask >>= 1)
            {
                putchar((arr[i] & mask)? '1' : '0');
            }
            putchar(' ');
        }
        putchar('\n');
    }
    
    
    /*
    my output:
    
    before:
    01001111 00000000 11111111
    After rotating left 10 times:
    00000011 11111101 00111100
    
    */
    Looks right to me...
    Last edited by whiteflags; 12-02-2019 at 12:06 AM.

  10. #10
    Registered User
    Join Date
    Dec 2017
    Posts
    15
    After read yors codes and with yos helps, final y arrive at one final solution. One combiation beatwine shift left and shif right.

    Thanks evoryone. But special to John.c for her patience.


    This is mycode

    Code:
    #include <stdio.h>
    typedef unsigned char byte;
    // *ar - variable array
    //size - array lengt
    //Shift- number s shifts
    //input - Input bit left or right into byte
    //lr - Shift left=0 or Shift right=1
    void shift_left_right(byte *ar, int size, int shift, byte input, byte lr) {
        while (shift-- > 0) {
            byte carry = 0;
            int k;
            if (!lr) {
                for (k = size; k-- > 0;) {
                    if (k > 0 & !lr) {
                        carry = (ar[k - 1] & 0x80) >> 7;
                    } else {
                        if (input) {
                            carry = 0x01;
                        } else {
                            carry = 0x00;
                        }
                    }
                    ar[k] = (ar[k] << 1) | carry;
                }
            } else {
                for (k = 0; k < size; k++) {
                   if (input & (k=size-1)) {
                    carry = 0x80;
                   } else {
                  carry = (ar[k + 1] & 0x01)<<7;
                   }
                    ar[k] = (ar[k] >> 1) | carry;
                }
            }
        }
    }
    
    
    
    void imprime(byte texto)
    {
        for (int i = 0; i < 8; i++)
            putchar('0' + !!((texto << i) & 0x80));
       // putchar('\n');
    }
    int main()
    {
        byte alfabeto[8] ={0b11111111, 0b00000011, 0b00000000, 0b00000000,0b00000000, 0b00000000, 0b00000000, 0b00000001};
       shift_left_right(alfabeto, 8, 4,0,0);
    
        for (int i = 7; i>=0 ; i--)
            imprime(alfabeto[i]);
        return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bitwise Operator Shift
    By YannB in forum C Programming
    Replies: 14
    Last Post: 03-04-2014, 09:49 PM
  2. homework help bitwise shift
    By progmateur in forum C Programming
    Replies: 1
    Last Post: 03-30-2013, 03:00 PM
  3. How to shift an array and add a char to the middle?
    By vertigodown in forum C Programming
    Replies: 3
    Last Post: 04-22-2012, 04:46 AM
  4. Bitwise Shift
    By blurx in forum C Programming
    Replies: 2
    Last Post: 10-12-2008, 09:39 AM
  5. Bitwise Shift Operations
    By John_L in forum Tech Board
    Replies: 19
    Last Post: 02-25-2008, 11:22 AM

Tags for this Thread