# how to pack 8 x 4 bit binary numbers into a long int?

• 11-18-2001
n00bcodezor
how to pack 8 x 4 bit binary numbers into a long int?
How do I pack 8 4-bit binary numbers into a long int?
The program is to take an input string of 8 ascii charcaters, (digits 0 to 9 only), convert them to their 4 bit binary equivilants and pack them into a long int.

eg:
input string: 13560927

= 0001 0011 0101 0110 0000 1001 0010 0111.

thanks...
• 11-18-2001
Salem
So which bit are you stuck on?
- extracting digits
- storing the bits in a long int?

All you need is a loop and some use of
result = result << 4;
• 11-18-2001
Sayeh
Technically, a 4-bit number is a called 'nyble'. half of a byte.

working with nybles is easy-- just use masking and shifting. In fact, this is one of the reasons it is easier to work in hex than it is, in decimal, because hex naturally breaks up into nybles.

0x0 through 0xF = 0-15 decimal = 0000 to 1111 binary.

0001 0011 0101 0110 0000 1001 0010 0111

just shift and 'and' (logic operation).

---

unsigned long newlong;
unsigned long scratch;

char string[] = '13560927];
int i;

newlong = 0L; /* clear to zero */

for(i=0;i<8;i++)
{
scratch = (long)atoi(string[i]);
scratch <<= ((7-i)*4);

newlong &= scratch;
};

You should end up with a number that is: 0x13560927 hex.

enjoy.
• 11-18-2001
n00bcodezor
sayeh, what exactly do the lines

scratch <<= ((7-i)*4);

newlong &= scratch;

• 11-18-2001
goran
newlong &= scratch;

we eventually end up with zero in newlong because it has been initialized to zero.

i m still trying to figure it out sayeh's code..
• 11-18-2001
doubleanti
he probably meant |=

scratch-line shifts the data over the correct number of bits to prep it...

or-line stores that prepped data into the long int you want...
• 11-19-2001
n00bcodezor
ok here is my modification of his code (but it still doesnt work :D)

anyone care to debug it for me?

#include <stdio.h>

int main()
{
unsigned long newlong;
unsigned long scratch;

char string[] = "13560927";
int i;

newlong = 0; /* clear to zero */

for(i=0;i<8;i++)
{
scratch = (long)atoi(string[i]);
scratch <<= ((7-i)*4);

newlong |= scratch;
}
printf("%i", scratch);
getch();

return 0;
}
• 11-19-2001
ozgulker
Well atoi accepts a string as its argument and it converts to integer. atol is for longs but your arguments are all chars so your code will cause segmentation faults. Here is the corrected full program.

#include <stdio.h>
#include <conio.h>

void displayBits(unsigned long);

int main()
{
unsigned long newlong;
unsigned long scratch;

char string[] = "13560927";
int i;
char dummy;

newlong = 0; /* clear to zero */

for(i=0;i<8;i++)
{
dummy = (string[i] & 0x0f);
scratch = (unsigned long) dummy;
scratch <<= ((7-i)*4);

newlong |= scratch;
}

printf("string is: %s\n", string);
printf("packed in %ld\n", newlong);
displayBits(newlong);

getch();

return 0;
}

void displayBits(unsigned long value)
{
unsigned long c, displayMask = 1 << 31;

for (c = 1; c <= 32; c++) {
putchar(value & displayMask ? '1' : '0');
value <<= 1;

if (c%4 == 0)
putchar(' ');
}
putchar('\n');
}
• 11-19-2001
n00bcodezor
thanks for that ozgulker.

works like a charm
• 11-19-2001
Sayeh
Thank you for all the help people-- I injured a muscle in my jaw here several weeks ago, and sometimes the pain makes it hard to concentrate.

Typos result.

(Oh well, better now)--

This little line means:

scratch <<= ((7-i)*4);

Take 'scratch', shift it left 4 bits for every iteration through the loop, and make it equal to that value. However, since our loop is counting 'left to right' per se, we need to reverse the direction of the count. hence "(7-i)".

So for example, when examining the first character, we see that it is a '1'. Our loop is at zero.

'1' in binary = 0000 0000 0000 0000 0000 0000 0000 0001

newLong == 0x00000000

So, doing the calculation, we want to shift the '1' left by

(7-0)*4) = x
7*4 = x
28 = x

shift the '1' left by 28 bits. Like so:

0001 0000 0000 0000 0000 0000 0000 0000

newLong == 0x10000000

---

The next number is a '3', and our loop is at '1', so:

0000 0000 0000 0000 0000 0000 0000 0011

via the math:

(7-1)*4) = x
6*4 = x
24 = x

becomes:

0000 0011 0000 0000 0000 0000 0000 0000

Then when we OR it with the newLong value:

newLong == 0x13000000

---

and so on.

enjoy.
• 11-19-2001
n00bcodezor
thanks for that explanation sayeh, i understand it all now.
• 11-19-2001
quzah
Here's a fun one:
Code:

```typdef union pack {     struct {         int n0:4;         int n1:4;         int n2:4;         int n3:4;         int n4:4;         int n5:4;         int b6:4;         int n7:4;     } nyb;     long l; } PACK; long cram( long l, int spot ) {     PACK p;     switch( spot%8 )     {         case 0: p.n0 = l%16; break;         case 1: p.n1 = l%16; break;         case 2: p.n2 = l%16; break;         case 3: p.n3 = l%16; break;         case 4: p.n4 = l%16; break;         case 5: p.n5 = l%16; break;         case 6: p.n6 = l%16; break;         case 7: p.n7 = l%16; break;     }     return p.l; }```
See how much fun that was? :) You could likely use an array of structures of integer x:4; but I haven't tried it, and I know this way will work. If you could use an array of nyb, then you could forgo the case statement with a single line:

p.n[spot%8] = l%16;

Quzah.