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

1. ## 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

2. ## Re: unpacking after an "or" and a "shift"

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

3. ## Re: Re: unpacking after an "or" and a "shift"

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

4. 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. 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.

5. ## 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

6. 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.

7. >> 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.

8. 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);```

9. Either declare shift of type unsigned int, or add some casting to unsigned int when you break out the two characters.

10. 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.

11. 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())
{
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();```

12. oh yeah, i figured this out a while ago.

Code:
`combine = ((unsigned int) (unsigned char)Cha<<8) | (unsigned int) (unsigned char)Chb;`

13. 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;```