0

I have an unsigned char at 6 bytes long. The value being stored within the char is:

Hex: 53167DFD95B7
Binary: 010100 110001 011001 111101 111111 011001 010110 110111

What I need to do is capture bit 1 and bit 6. Then convert that to a decimal. Then capture bit 2-5 and convert that to decimal For example, bit 1 here is 0, bit 6 is 0, so binary 00, is decimal 0. Then for bit 2-5, binary 1010, or decimal 10. Then move to the next group of 6 bits.

Bit 1 is 1, Bit 6 is 1, so binary 11, or decimal 3 Bit 2-5 is binary 1000, or decimal 8

Bit 1 is 0, Bit 6 is 1, so binary 01, or decimal 1 Bit 2-5 is binary 1100, or decimal 12

And so on for the remaining groups of 6 bits.

I'm not really sure how I should be masking, shifting for this. Since this is only 6 bits at a time I am having some difficulty. Any help with this would be greatly appreciated! Thank you all in advance.

EDIT

int getBitVal(unsigned char *keyStrBin, int keyIndex) {

    int keyMod = keyIndex % 8;  
    int keyIn = keyIndex / 8;

    return (((keyStrBin[keyIn]) >> (7 - (keyMod))) & 1);

}
void getSValueMajor(char **tableS, unsigned char *f, unsigned char *sValue) {
    int i, bitOne, bitSix;
    int sCol;

    for (i = 0; i < 8; i++) {
        bitOne = getBitVal(f, 0);
        bitSix = getBitVal(f, 5);
        // Do something here to get only bits 2-5. Doesn't matter if its decimal. Just need the 4 bits.

    }

}

Ill shift by 6 bits I guess at the end of the loop to go to the next 6 bits, but not sure how to read those 4 bits into a variable.

TyrantUT
  • 29
  • 1
  • 5
  • Related: http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c-c?rq=1 – Vaughn Cato Mar 28 '16 at 04:39
  • This has the fragrance of a DES algorithm. – WhozCraig Mar 28 '16 at 04:39
  • Indeed. It's for a school project. – TyrantUT Mar 28 '16 at 04:41
  • You would do well to study to memory the bit manipulation covered in that answer then, as taking on DES without a *strong* command of said-material is recipe for many, *many* hours of frustration. – WhozCraig Mar 28 '16 at 04:47
  • Makes sense, but rather than re-inventing the wheel for this specific section, I'll reach out to the community. Do you have constructive input that might come to an answer in this public forum? I am familiar with bit manipulation. I can grab bit 1, bit 6 fine. But not a bit range as a decimal... – TyrantUT Mar 28 '16 at 04:56
  • @TyrantUT Actually it doesn't really matter if the result is decimal or not. – HenryLee Mar 28 '16 at 05:04
  • 3
    You should try doing it yourself, if you are familiar with bit manipulation. First, try the first 3 bytes (first 4 groups of 6-bit numbers), then you can come up with a loop the do the rest. – HenryLee Mar 28 '16 at 05:06
  • 1
    You'll do yourself a big favor by taking some action, then coming back to describe what you've done. Many users come to this website looking not for help, but for someone to do their work for them; showing your efforts is very encouraging to those who volunteer their time here to help. :) – jrsmolley Mar 28 '16 at 05:14
  • 'void getSValueMajor(char **tableS, unsigned char *f, unsigned char *sValue) { int i, bitOne, bitSix; int sCol; for (i = 0; i < 8; i++) { bitOne = getBitVal(f, 0); bitSix = getBitVal(f, 5); // Do something here to get only bits 2-5. Doesn't matter if its decimal. Just need the 4 bits. } }' Good god, no formatting in comments?? – TyrantUT Mar 28 '16 at 05:23
  • No, no, they meant actually include that code in your Question. Just edit your question and indent all code by an initial 4-spaced (for fixed-font formatting). The remainder of your code should be properly indented as well. – David C. Rankin Mar 28 '16 at 05:32

1 Answers1

0

I've updated this because a commenter mentioned that it wasn't using real numbers. I know this but the point was to leave something up to the person doing their homework.

The following is not a neat answer to this but it should give anyone coming to this an idea on how to solve it in a neat way. In the second method I used a string as the thing I'm converting and converted this to a binary number and from there I've performed a few bit manipulations.

With everything in bit fiddling there are always ways to speed things up ie you could use Masks for all 8 bytes to avoid some shifts, you could also unroll the loop etc.

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 010100 == 00 , 1010 === 0 , 10 
 110001 == 11 , 1000 === 3 , 8
 011001 == 10 , 1100 === 2 , 12
 111101 == 11 , 1110 === 3 , 14
 111111 == 11 , 1111 === 3 , 15
 011001 == 01 , 1100 === 1 , 12
 010110 == 00 , 1011 === 0 , 11
 110111 == 11 , 1011 === 3 , 11
*/
int main(void) {
  size_t x = 48; 
  size_t v = 91356068156855;

  size_t one66 = 0;
  size_t two55 = 0;
  size_t bit1  = 0;
  size_t bit6  = 0;

  //Masks
  size_t sixty3 = 63; 
  size_t thirty = 30; 

  size_t b[8];
  b[0] = (v & (sixty3 << 42ULL)) >> 42ULL;
  b[1] = (v & (sixty3 << 36ULL)) >> 36ULL;
  b[2] = (v & (sixty3 << 30ULL)) >> 30ULL;
  b[3] = (v & (sixty3 << 24ULL)) >> 24ULL;
  b[4] = (v & (sixty3 << 18ULL)) >> 18ULL;
  b[5] = (v & (sixty3 << 12ULL)) >> 12ULL;
  b[6] = (v & (sixty3 << 6ULL))  >> 6ULL;
  b[7] = (v & (sixty3 << 0ULL))  >> 0ULL;

  for(x = 0; x < 8;x++) {
    one66 = 0;
    two55 = 0;
    bit1 = (b[x] & 1)  > 0;
    bit6 = (b[x] & 32) > 0;
    one66 |= bit1 << 1;
    one66 |= bit6 << 0;
    two55 = (b[x] & thirty) >> 1;
    printf("%zu %zu\n", one66, two55);
  }

 // Method 2 using a string as the input...
 //                    |     |     |     |     |     |     |     |      
  char     pat[]     = "010100110001011001111101111111011001010110110111";
  size_t   patlength = strlen(pat);
  for(x = 0; x < patlength; x += 6) {
    size_t one6 = 0;
    size_t two5 = 0;
    if(pat[x] == '1') {
      one6 |= 1ULL << 0;
    }
    if(pat[x + 5] == '1') {
      one6 |= 1ULL << 1;
    }
    assert(one6 < 4);
    if(pat[x + 1] == '1') {
      two5 |= 1ULL << 3;
    }
    if(pat[x + 2] == '1') {
      two5 |= 1ULL << 2;
    }
    if(pat[x + 3] == '1') {
      two5 |= 1ULL << 1;
    }
    if(pat[x + 4] == '1') {
      two5 |= 1ULL << 0;
    }
    assert(two5 < 16);
    printf("%zu %zu\n", one6, two5);
  }
  return 0;
}
Harry
  • 11,298
  • 1
  • 29
  • 43
  • 1
    I believe the input is not a string of 0s and 1s. And it would take too much computing effort to convert the bytes to such a string. – HenryLee Mar 28 '16 at 11:05
  • @HenryLee I've updated the answer to do it on a real number as well. – Harry Mar 28 '16 at 18:16