0

I have a program that my professor gave me for a HW, and I want to see if any of y'all can explain me how bits work. Note: I don't want you guys to give me the answer; I want to learn so if you guys can explain me how this work would be awesome so I can go ahead an start on my hw.

Instructions:

a) unsigned setbits (unsigned x, int p, int n, unsigned y) that returns x with the n bits that begin at position p (right-adjusted) set to the rightmost n bits of y, leaving the other bits unchanged. Note: it does not change the values of x and y though.

b) unsigned invertbits (unsigned x, int p, int n) that returns x with the n bits that begin at position p (right-adjusted) inverted, i.e. 1 changed to 0 and vice versa, leaving the other bits unchanged. Note: it does not change the value of x though.

#include <stdio.h>
#include <limits.h>

void bit_print(int);
int pack(char, char, char, char);
char unpack(int, int);
unsigned getbits(unsigned, int, int);

void bit_print(int a){
    int i;
    int n = sizeof(int) * CHAR_BIT;
    int mask = 1 << (n-1); // mask = 100...0

    for (i=1; i<=n; i++){
        putchar(((a & mask) == 0)? '0' : '1');
        a <<= 1;
        if (i % CHAR_BIT == 0 && i < n)
            putchar(' ');
    }
    putchar('\n');
}

int pack(char a, char b, char c, char d){
    int p=a;
    p = (p << CHAR_BIT) | b;
    p = (p << CHAR_BIT) | c;
    p = (p << CHAR_BIT) | d;
    return p;
}

char unpack(int p, int k){    // k=0, 1, 2, or 3
    int n = k * CHAR_BIT; // n = 0, 8, 16, 24
    unsigned mask = 255;  // mask = low-order byte

    mask <<= n;
    return ((p & mask) >> n);   
}

// getbits() extracts n bits from position p(start counting from the right-most bit) in x
unsigned getbits(unsigned x, int p, int n){
    unsigned temp = x >> (p+1-n);

    unsigned mask = 0;
    mask = ~mask;
    mask = mask << n;
    mask = ~mask;

    return temp & mask;
    // return (x >> (p+1-n)) & ~(~0<<n);
}

int main(){
    int x = 19;

    printf("The binary rep. of %d is:\n", x);
    bit_print(x);

    int p=pack('w', 'x', 'y', 'z');
    printf("\n'w', 'x', 'y', and 'z' packed together is equal to %d. Its binary rep. is:\n", p);
    bit_print(p);
    printf("calling unpack(p, 0) to extract the byte # 0 from the right:\n");
    bit_print(unpack(p, 0));
    printf("calling unpack(p, 1) to extract the byte # 1 from the right:\n");
    bit_print(unpack(p, 1));
    printf("calling unpack(p, 2) to extract the byte # 2 from the right:\n");
    bit_print(unpack(p, 2));
    printf("calling unpack(p, 3) to extract the byte # 3 from the right:\n");
    bit_print(unpack(p, 3));

    unsigned result = getbits(p, 20, 7);
    printf("\ncalling getbits(p, 20, 7) to extract 7 bits from bit # 20 returns %d:\n", result);
    bit_print(result);

    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Do you have a specific question? How bits work is pretty broad and it seems like it would be covered in your course before this homework was assigned. – Retired Ninja Sep 03 '14 at 16:23
  • @RetiredNinja they gave us an intro but I didn't understand –  Sep 03 '14 at 16:42

1 Answers1

1

Using bitwise AND & , OR |, XOR ^, NOT ~ and a proper bit mask you can manipulate bits inside a variable. You will also need bit shifts >> and <<.

So let us have an example:

Let's take a 8bit var x = 0xff and try to invert its 3'rd bit:

unsigned char x = 0xff;    // Our var
unsigned char mask = 1<<3; // Our mask
x = x & ~mask; // Invert mask so its value is b1111_0111 
               // and make a bitwise AND with x

Every bit in x keeps its value if there is 1 in a mask, and turns into 0 when masks bit value is 0. Now x value is x = 0xf7. Using other operators you can do whatever you want with bits :)

So for example yours unpack function does:

char unpack(int p, int k){   // k - byte offset
   int n = k * CHAR_BIT;     // n - bit offset (k * 8)
   unsigned mask = 255;      // mask with all ones at first byte (0x000f)
   mask <<= n;               // move mask left n times; 
                             // Now the ones are at the k'th byte 
                             // if k = 2 => mask = 0x0f00
   return ((p & mask) >> n); // Mask out k'th byte of p and remove all zeros 
                             // from beginning. 
}

When p = 0x3579 and k = 1:

n = k * CHAR_BIT; // n = 8
mask = 255;       // mask = 0x000f
mask <<= n;       // mask = 0x00f0
p &= mask;        // p = 0x0070
p >>= n;          // p = 0x0007

I hope it will help you!

kleszcz
  • 96
  • 6