开发者

How to print a variable in reversed byte order?

I'm trying to convert the variable $num into its reverse byte order and print it out:

my $num = 0x5514ddb7;
my $s = pack('I!',$num);
print "$s\n";

It's printing as some non-printable characters and in a hex editor it looks right, but how can I get it readable on the console? I already tried this:

print sprintf("%#x\n",$s);

This makes perl complain about a non-numeric argument, so I think pack returns a string. Any ideas how can I print out 0开发者_如何学Pythonxb7dd1455 on the console, based on $num?


You need to use unpack:

my $num = 0x5514ddb7;
my $s = pack('I<!',$num);
my $x = unpack('I>!',$s);
printf("%#x\n",$x);

Comment from Michael Carman: Be aware that byte-order modifiers (<and >) require Perl v5.10+. For older versions of Perl you'd have to use the N and V templates instead.


my $num=0x5514ddb7;
my $i = unpack('N', pack('V',$num));
printf("0x%x\n", $i);

But are you sure you want to do this? It's 32-bit-specific. The question begs for a "why do you ask?" in order to suggest something better than whatever it is you're trying to solve.


You need to use CORE::unpack() "H" (capital H):

H   A hex string (high nybble first).

my $num=0x5514ddb7;
my $s=pack('I!',$num);
print unpack ("H*", "$s") . "\n"; # b7dd1455


As a mostly-C programmer who dabbles in perl, my immediate instincts are to slice and dice with bitwise operators:

$n2 = ($num & 0xff) <<24
    | ($num & 0xff00) <<8
    | ($num & 0xff0000) >>8
    | ($num & 0xff000000) >>24 ;

But, this being perl, there are undoubtedly many ways to achieve the same result, and there's probably a good perl idiom for this.


Thought I would chime in for those of us who need to examine formatted binary files. This is what I use when the spec shows the hex values in non-Intel byte order like the MySQL .frm spec. You can specify bigger chunks by increasing the sysread size. The pack/unpack lengths must be 2 x the sysread value. The offset += [set to sysread value].

#!/usr/bin/perl
BEGIN {
    use Getopt::Long;

    $reverse=0;
    GetOptions ("reverse" => \$reverse);

}

my $f=STDIN;
if (int(@ARGV))
{
    open(IN, $ARGV[0]) or die "Failed to open $ARGV[0] for reading.\n$!";
    $f=IN;
}

my $count=1;
my $offset=0;
my $after_nl=1;
while (sysread($f,$buf,2))
{
    my $hex = unpack('H4', $buf);
    $hex=join("",(split(//,$hex))[2,3,0,1]) unless $reverse;
    if (($count % 8) == 0)
    {
        printf "%s\n", $hex;
        $after_nl=1;
        $offset += 2;
    }
    else
    {
        printf "%08x ", $offset if $after_nl;
        printf "%s ", $hex;
        $offset += 2;
        $after_nl=0;
    }

    $count++;
}


$num = 0x5514ddb7;
print '0x', sprintf( '%08x', $num ) =~ /../g;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜