Qckng has asked for the wisdom of the Perl Monks concerning the following question:

What am I doing wrong?
while (<STDIN>) { chomp; $Pack = pack("H2", $_); print ":$_: packs to :$Pack:\n"; $Un = unpack("H2", $Pack); print ":$Pack: unpacks to :$Un:\n"; }
I'm getting:
-1
:-1: packs to :Ñ:
:Ñ: unpacks to :d1:
-2
:-2: packs to :Ò:
:Ò: unpacks to :d2:
-3
:-3: packs to :Ó:
:Ó: unpacks to :d3: 
and so on, thru 9. The commercial software is giving me the correct packed character. How can I unpack it to the original negative number (or really, a string of "-1")?

Thanks,
Kyle

Mini-edit by castaway, swapped runaway bold tag for a br, swapped strange chars for &#xd1; etc (as my browser killed em in the first edit, oops)

Replies are listed 'Best First'.
Re: H2 pack/unpack not working for negative numbers
by nevyn (Monk) on Dec 10, 2003 at 18:04 UTC

    I think what you are looking for is one of...

    perl -le 'print unpack("c", pack("c", -1))' perl -le 'print unpack("i", pack("i", -1))'

    H2 means 2 hex strings, which are unsigned. i and/or c work with numbers, and hex/decimal/etc. are transparent to them.

    --
    James Antill
      I mentioned I don't have a choice in how the string is packed. Even if the "wrong packing" was used for a string = "-1" , how can I unpack it back to "-1"? Another way of saying it is, both strings "-1" and "d1" pack with H2 to the same character (squiggly N). If I know ahead of time it must be an integer, what unpacking can I use to get "-1"

      Kyle

        Before you can decide, or we can help you decide, which format specifier is the correct one to use, you will need to know how the information you are trying to unpack was packed.

        For example, you mention an integer. An integer could be

        1. An 8-bit integer (byte),
          • signed (-128 .. +127)
          • unsigned (0 .. 255)
        2. A 16-bit integer (2 bytes/1 word)
          • Signed (-32768 .. 32767 )
          • Unsigned (0 .. 65535)
        3. A 32-bit integer (4 bytes/2 words/dword/long)
          • Signed (-2147483648 .. 2147483647)
          • Unsigned (0 .. 4294967295)
        4. A 64-bit integer (8 bytes/4 words/quadword/long long (etc!)) ....

        There are other formats but these are the most common.

        Add to this, the possibility that some machines pack binary values into words in different (byte) orders. So called litte-endian and big-endian and with the exception of 1) above, you can double each of those possibilities, which is why pack/unpack have so many format specifiers for "integers": N n V v S s C c.

        Which you need to use could be any of these, but as a guess, s, n, & v seem the most likely candidates. H seems the least likely.

        In other words. You need to supply more information:)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!

        Use what you have and then s/d/-/ on the result ;-)