Moving bits to bytes using a bit field or bitwise operators

Is there an elegant way to move bits in bytes (or word / long). For simplicity, you can use a simple 8-bit byte and only one bit to move inside the byte.

Given the number of bits based on 0-7 least-sig bits for most sig bits (or bits 1-8 if you prefer), I would like to move a little from one position to another

7654 3210 <bit position
0101 1010 <some binary value
--x- --y- <move bit from x to y
0111 0100 <new value with x moved to y and intervening bits shifted left

So, x at position of bit 5 moves to y at position of bit 1, bit 0.6.7 remains unchanged. Bits 2,3,4 are shifted to the left to β€œmake room” for bits shifted from 5 to 2. This is just an example.

It is important that the bit is moved, not changed for the purpose. There are many examples of bits that change, but this is pretty trivial.

Ideally, this solution would use simple bit-woven and bitwise operators. Suppose an agnostic language, a simple bit AND / OR / XOR, NOT, SHIFT Left / Right / ROTATE or similar instructions would be good in any combination, plus any other basic arithmetic operator, for example: mod, addition / subtraction, etc. . Even working psuedo- code will be fine. Alternatively, the structure of a bitmap or bitfield type would probably be simple.

In addition to actually moving the bits, I would like to find a way:

  • Move any bit up or down.
  • Indicate the source / destination of the bit number in any convenient format: for example: 6> 2 means a shift down, 3> 7 a shift up or the initial bit +/- shift: 6-4 or 3 + 4 or a weighted bit: bit 6 = 64 bit 3 = 8.
  • Extension from byte to unsigned int, long, etc. is possible.
  • ( , , , , )

, - , , .

, , , , , - / . , , .

, , /longs, .

. .

+5
4

-, , :

" ", , . 1-5 :

  7   6   5   4   3   2   1   0          7   6   5   4   3   2   1   0
+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+---+---+
| 0 | 1 | 0<--1<--1<--0<--1 | 0 |  ->  | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
+---+---+-|-+---+---+---+-^-+---+      +---+---+---+---+---+---+---+---+
          |               |
          +---------------+

" , " :

  • ,

, , :

  • , , ( / );
  • , n , k - , , n-k ,
  • ;
  • .

, ...


, , .

0 - n, 1 n + 1 , 1. . 0-5 ( ):

00111111

... 1:

00000001

... 5 + 1 = 6 :

01000000

... 1, :

00111111

C (1 << (bit + 1)) - 1. , C ( , -, , , , ): ( ) undefined. , 0-7 8- , (1 << 8) - 1, undefined. ( , .) undefined , .

, C unsigned (1 << bit) + (1 << bit) - 1. n- , 2 n , .

( .)

, 0 - msb. lsb - msb, , 0 - (lsb-1), (1 << lsb) - 1. .

  00111111      mask for bits 0-5:  (1 << 5) + (1 << 5) - 1
- 00000001      mask for bits 0-0:  (1 << 1) - 1
  --------                         -------------------------------
  00111110      mask for bits 1-5:  (1 << 5) + (1 << 5) - (1 << 1)

, :

mask = (1 << msb) + (1 << msb) - (1 << lsb);

, , :

to_rotate = value & mask;

... , , :

untouched = value & ~mask;

: -, , to_rotate , :

left = (to_rotate << shift) & mask;

, to_rotate (n - shift) , n - , ( n msb + 1 - lsb):

right = (to_rotate >> (msb + 1 - lsb - shift)) & mask;

, untouched, left right:

result = untouched | left | right;

(msb is 5, lsb 1, shift 1):

    value = 01011010

    mask  = 00111110   from (1 << 5) + (1 << 5) - (1 << 1)

            01011010   value
          & 00111110   mask
          ----------
to_rotate = 00011010

            01011010   value
          & 11000001   ~mask  (i.e. inverted mask)
          ----------
untouched = 01000000

            00110100   to_rotate << 1
          & 00111110   mask
          ----------
     left = 00110100

            00000001   to_rotate >> 4  (5 + 1 - 1 - 1 = 4)
          & 00111110   mask
          ----------
    right = 00000000

            01000000   untouched
            00110100   left
          | 00000000   right
          ----------
   result = 01110100

16- msb= 15, lsb= 4 shift= 4 ( 3 4- ):

    value = 0101011001111000   (0x5678)

    mask  = 1111111111110000   from (1 << 15) + (1 << 15) - (1 << 4)

            0101011001111000   value
          & 1111111111110000   mask
          ------------------
to_rotate = 0101011001110000

            0101011001111000   value
          & 0000000000001111   ~mask
          ------------------
untouched = 0000000000001000

            0110011100000000   to_rotate << 4
          & 1111111111110000   mask
          ------------------
     left = 0110011100000000

            0000000001010110   to_rotate >> 8  (15 + 1 - 4 - 4 = 8)
          & 1111111111110000   mask
          ------------------
    right = 0000000001010000

            0000000000001000   untouched
            0110011100000000   left
          | 0000000001010000   right
          ------------------
   result = 0110011101011000   =  0x6758
+4

C, , . ints, (, ). - , .

//
// bits.c
//

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

//
// extract_bit
//
// extract bit at given index and move less significant bits left
//

int extract_bit(int *word, int index)
{
    int result = (*word & (1 << index)) != 0;
    int mask = (1 << index) + (1 << index) - 1;
    *word = ((*word << 1) & mask) | (*word & ~mask);
    return result;
}

//
// insert_bit
//
// insert bit at given index and move less significant bits right
//

void insert_bit(int *word, int index, int val)
{
    int mask1 = (1 << index) + (1 << index) - 1;
    int mask2 = (1 << index) - 1;
    *word = ((*word >> 1) & mask2) | (*word & ~mask1) | (val << index);
}

//
// move_bit
//
// move bit from given src index to given dest index
//

int move_bit(int *word, int src_index, int dest_index)
{
    int val = extract_bit(word, src_index);
    insert_bit(word, dest_index, val);
    return val;
}

int main(int argc, char * argv[])
{
    if (argc > 2)
    {
        int test = 0x55555555;
        int index1 = atoi(argv[1]);
        int index2 = atoi(argv[2]);

        printf("test (before) = %#x\n", test);
        printf("index (src) = %d\n", index1);
        printf("index (dest) = %d\n", index2);

        move_bit(&test, index1, index2);

        printf("test (after) = %#x\n", test);
    }

    return 0;
}
+2

, , "", , ? , ( , ?), , .

              Number: 01x1 10y1
       P1 (before x): 0100 0000
     P2 (just bit x): 00x0 0000
P3 (between x and y): 0001 10y0
        P4 (after y): 0000 0001

Then the number you need [P1] + [P3 shifted up by 1] + [P2 shifted down by 4] + [P4].

                  P1: 0100 0000
P2 shifted down by 3: 0000 00x0
  P3 shifted up by 1: 0011 0y00
                  P4: 0000 0001

                 Sum: 0111 0yx1               
+1
source

Do you use bits to save space? Is it really necessary?

You might be better off with a list class that allows you to remove and insert items into a list. In your case, the elements will have a Booleans value.

0
source

All Articles