# unpacking after an "or" and a "shift"

• 08-04-2003
keithmolo
unpacking after an "or" and a "shift"
hi everyone.

right now i have read in two characters and combined them into an int. Once i have combined them, i have shifted the whole thing over.

Now i need to take the combined shift and unpack it to two separate entities again. Here is my code so far.

while(!fIn.eof()) {
fIn.get(Cha);
fIn.get(Chb);
combine = ((int)Cha<<8) | (int)Chb;
shift = (combine << 4);
}

Is what i'm looking to do remotely possible? If so, can anybody help me out? Thanks much!

Keith
• 08-04-2003
FillYourBrain
Re: unpacking after an "or" and a "shift"
Quote:

Originally posted by keithmolo
fIn.get(Cha);
fIn.get(Chb);
combine = ((int)Cha<<8) | (int)Chb;
shift = (combine << 4);

all you have to do is reverse the steps.

combine = shift >> 4;
Cha = combine >> 8;
Chb = combine & 0xFF;

done
• 08-04-2003
keithmolo
Re: Re: unpacking after an "or" and a "shift"
Quote:

Originally posted by FillYourBrain

Cha = combine >> 8;
Chb = combine & 8;

could you please explain how this works? I understand the unpacking part, but am unfamiliar with what values the chars would be taking on. Also, what does the & do in this particular case?

thanks,
keith
• 08-04-2003
FillYourBrain
Cha = combine >> 8;
This line does a shift right of 8 bits. It takes the "leftmost" 8 bits and moves them into the right. This allows the resulting char to be just those bits.

Chb = combine & 8;
This was a brain fart. :eek: I actually meant this:

Chb = combine & 0xFF;
this line does a bitwise "and" operation. It preserves only the rightmost 8 bits of the int to be stored in Chb.
• 08-05-2003
keithmolo
not working with some numbers
for testing purposes of my code, i created a dat file with the following hex code:

------------------------------------------------------------------
01 02 03 04 05 06 07 08 :: F8 F9 FA FB FC FD FE FF
------------------------------------------------------------------

given my code, and, provided, this is in a loop:

Code:

```fIn2.get(xCha); fIn2.get(xChb); (unsigned int)combine = ((unsigned int)xCha<<8)|(unsigned int xChb; (unsigned int)shift = (combine << 4); xCha = (shift >> 8); xChb = (shift & 0xFF); fout.put(xChb); fout.put(xCha);```
i believe it should write hex code that looks like so:

-------------------------------------------------------------
20 10 40 30 60 50 80 70 :: 90 8F.....and so on
-------------------------------------------------------------

but the code seems to have trouble when it hits the negative hex numbers, because it looks like this:

Code:

`20 10 40 30 60 50 80 70 :: 90 FF B0 FF D0 FF F0 FF`
In fact, it writes FF's for every other character across the board. I am stumped!

Any ideas?
Thanks,
Keith
• 08-05-2003
VirtualAce
The problem is the sign bit. The sign bit tells the computer to use the two's complement mantissa form of the number to display its value.

Negatives are found by flipping the sign bit, adding 1 to the number, and finding the complement of it or vice versa, I forget.

It is possible if you find the complement of those larger numbers, you will get your negative ones. But w/o diving into it myself, I'm not positive as of yet.

But you should not be getting negatives since you are using unsigned int - which is using all bits to represent values. In negative numbers one of the bits is used as the sign bit. Hence that is why signed short integers have a range from -32768 to 32767 and unsigned shorts have a range of 0 to 65535.

• 08-05-2003
Perspective
>> Negatives are found by flipping the sign bit, adding 1 to the number, and finding the complement of it or vice versa, I forget.

i believe you flip all of the bits and negate the resulting value to find the value of a negative binary in 2's compliment.
• 08-06-2003
Cat
Flip all the bits and add one, actually, but interesting mathematics aside, if you declare everything as unsigned int, you should never have any problems, anywhere. In fact, the sign bit is always unset, because you never shift anything into the highest byte of the word (I'm assuming your ints are 32 bits; on a 16 bit system this "packing" would lose information.)

Code:

```(unsigned int)combine = ((unsigned int)xCha<<8)|(unsigned int xChb;//Your previous code could undo this line (unsigned int)shift = (combine << 4);//But you never undid this one. xCha = (shift >> 12); xChb = ((shift >> 4) & 0xFF);```
The operations you had would undo the combine, but they wouldn't undo the shift -- so you'd either have to shift the other way before doing the unpacking, or make the changes I posted. The other way is this:

Code:

```(unsigned int)combine = ((unsigned int)xCha<<8)|(unsigned int xChb; (unsigned int)shift = (combine << 4); combine = shift >> 4; xCha = (combine >> 8); xChb = (combine & 0xFF);```
• 08-06-2003
swoopy
Either declare shift of type unsigned int, or add some casting to unsigned int when you break out the two characters.
• 08-06-2003
Cat
In general, it's a good idea to make things unsigned if you're doing bit shifting, but in this case, it makes no difference -- bits 20 through 31 are guaranteed to be zero because of how you create the packed version, so you CAN'T have problems unpacking because of it.
• 08-07-2003
swoopy
Cat, I played around with this, and am stumped. I took out the shift left 4, and when I run the following code, I get the same result as keithmolo. I wonder why?
Code:

```  ifstream fIn2(filename1, ios::binary);   if (!fIn2.is_open())   {       cout << "File not found: " << filename1 << endl;       return 1;   }   ofstream fout(filename2, ios::binary);   if (!fout.is_open())   {       cout << "File could not be opened: " << filename2 << endl;       return 1;   }   char xCha, xChb;   unsigned int combine, shift;   while (fIn2.get(xCha))   {       fIn2.get(xChb);       (unsigned int)combine = ((unsigned int)xCha<<8)|(unsigned int) xChb;       shift = combine;       xCha = (shift >> 8);       xChb = (shift & 0xFF);       fout.put(xChb);       fout.put(xCha);   }   fIn2.close();   fout.close();   in.open(filename2, ios::binary);   cout << endl;   char c;   while (in.get(c))   {       cout << hex << (int) c << endl;   }   in.close();```
• 08-07-2003
keithmolo
oh yeah, i figured this out a while ago.

Code:

`combine = ((unsigned int) (unsigned char)Cha<<8) | (unsigned int) (unsigned char)Chb;`
• 08-07-2003
swoopy
Interesting keithmolo. I was able to get it to work too by changing xCha and xChb to unsigned char's.
Code:

```  unsigned char xCha, xChb; . . .   combine = ((unsigned int)xCha<<8)|(unsigned int) xChb;```