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

I am still trying to understand pack and unpack at this time.

Here is a code sample

#!/usr/bin/perl -w use strict; my ($testp, $n, $s); $testp = 0x007102; $n = length($testp); $s = 2*$n; print ("Hex 0x",unpack("H$s", $testp), "\n"); $testp = "\x30\x05\x15"; $n = length($testp); $s = 2*$n; print ("Hex 0x",unpack("H$s", $testp), "\n");
The results are:
Hex 0x3238393330 Hex 0x300515
Expected results:
Hex 0x007102 Hex 0x300515
I am trying to understand why the differences in the processes above.

Another question about dealing with Hex values in perl, what is best way to do addition and multiplication, basic math? Convert to decimal and then to the math?

Thanks Mike

Replies are listed 'Best First'.
Re: Differences in behavior in pack
by apl (Monsignor) on Apr 08, 2008 at 20:38 UTC
    7102 hex == 28930 decimal

    '2' = ASCII 0x32
    '8' = ASCII 0x38
    '9' = ASCII 0x39
    '3' = ASCII 0x33
    '0' = ASCII 0x30

    Concatenate the hex of the characters and you get 0x3238393330, your mystery display.

Re: Differences in behavior in pack
by runrig (Abbot) on Apr 08, 2008 at 20:40 UTC
    For the first conversion, you want printf/sprintf, not unpack (and there's no telling how many zeroes you originally padded the number with):
    $testp = 0x007102; printf ("Hex 0x%x\n", $testp);
      Ok, so I guess to ask a better question?

      What is the difference in the way Perl stores these values? Is there away to tell the difference from a programmatic viewpoint if I am expecting hex values? What happens if the values are passed to my program either way?

      $testp = 0x007102; $testp1 = "\x30\x05\x15";
      Thanks again,
      Mike

        Technically, it's possible to tell the difference

        >perl -MDevel::Peek; -e"Dump(0x007102)" SV = IV(0x18265fc) at 0x2252f8 REFCNT = 1 FLAGS = (PADBUSY,PADTMP,IOK,READONLY,pIOK) IV = 28930 >perl -MDevel::Peek; -e"Dump(qq{\x30\x05\x15})" SV = PV(0x226680) at 0x225300 REFCNT = 1 FLAGS = (PADBUSY,PADTMP,POK,READONLY,pPOK) <-- Not IOK/UOK/NOK PV = 0x182f6a4 "0\5\25"\0 CUR = 3 LEN = 4

        But checking for that would be extremely fragile. I strongly recommend against that approach. Instead, use some kind of meta data (a different command line switch, for example) to specify the format, then canonize it for internal use.

        # Inputs my $input = "\x30\x05\x15"; my $packed = 1; # Canonize input if ($packed) { $input = unpack('N', substr(("\x00"x4).$input, -4)); } # Do some work #... # Output results printf("Results for 0x%X are %s\n", $input, "...");

        Update: Added second snippet.