unpacking after an "or" and a "shift"

This is a discussion on unpacking after an "or" and a "shift" within the C++ Programming forums, part of the General Programming Boards category; hi everyone. right now i have read in two characters and combined them into an int. Once i have combined ...

  1. #1
    Registered User
    Join Date
    Jul 2003
    Posts
    27

    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. #2
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297

    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
    Last edited by FillYourBrain; 08-04-2003 at 09:09 AM.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  3. #3
    Registered User
    Join Date
    Jul 2003
    Posts
    27

    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. #4
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    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.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  5. #5
    Registered User
    Join Date
    Jul 2003
    Posts
    27

    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. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,586
    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.

    Perhaps your causing your values to overflow the data type.

  7. #7
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    >> 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. #8
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    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.)

    Your unpacking is wrong, though.

    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);
    Last edited by Cat; 08-05-2003 at 11:12 PM.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Either declare shift of type unsigned int, or add some casting to unsigned int when you break out the two characters.

  10. #10
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    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. #11
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    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();
    Last edited by swoopy; 08-07-2003 at 12:58 AM.

  12. #12
    Registered User
    Join Date
    Jul 2003
    Posts
    27
    oh yeah, i figured this out a while ago.

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

  13. #13
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    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;

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21