Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re^2: converting artibrary binary data to numeric values

by markle (Initiate)
on Oct 01, 2012 at 19:48 UTC ( [id://996725]=note: print w/replies, xml ) Need Help??


in reply to Re: converting artibrary binary data to numeric values
in thread converting artibrary binary data to numeric values

Like with unpacking from numbers it seems Perl first converts the raw binary data into a string representation of a gigantic decimal number, then it tries to unpack from that, giving bizarre results that do not correspond to the original byte order.

Also, it seems the "b" and "B" flags to unpack expect the value to be a string of 1's and 0's, not a number.

Please help me answer my original question. How do I convert a value which perl thinks is the scalar "\xd\xe\xa\xd\xb\xe\xe\xf" into a scalar with the numeric value 0xDEADBEEF ?

  • Comment on Re^2: converting artibrary binary data to numeric values

Replies are listed 'Best First'.
Re^3: converting artibrary binary data to numeric values
by Corion (Patriarch) on Oct 01, 2012 at 20:17 UTC

    Are you really, really sure that you get eight bytes from your file, the first having the value 0x0D and the second having the value 0x0E (and so on)?

    If so, you might need to do some bit twiddling to combine all the nibbles:

    use Data::Dumper; my $str = "\x0D\x0E\x0A\x0D\x0B\x0E\x0E\x0F"; my @bytes = unpack 'C8', $str; print Dumper \@bytes; # Now add up the byte-pairs for (0..3) { $bytes[ $_ ] = $bytes[ $_*2 ] * 16 + $bytes[ $_*2 +1 ]; }; splice @bytes, 4; # we only need the first four entries print Dumper \@bytes; my $num = unpack 'N', pack 'C4', @bytes; print sprintf "%08x (%i)", $num, $num;

    But if you get a string of four bytes, one of the two pack templates "N" or "V" will help you. See the following:

    my $str = "\xDE\xAD\xBE\xEF"; my $num = unpack 'N', $str; print sprintf "%08x (%i)", $num, $num;

    But I already told you this and you didn't show any code.

      That doesn't seem reliable because it seems like "use bytes" doesn't affect the unpack C template. It seemed like when I tried that on arbitrary data and looked at the hex dump, some results were one byte and some were three.
      I'm still not sure what you mean. The C struct has unsigned longs mostly. Each of these is 32 bytes, right? So the data should line up, each value being 32 bytes from the raw data. If I use N or V, it seems that perl first converts the raw data to a number, then unpack tries to unpack the atring representation of that number in decimal. That's not what I want. I just want the values. Convert::Binary::C did the same thing.

        If you just want "the values", then keep them as strings. If that seems problematic, you have to show some code where you show how you acquire the data (say, from initializing a string), how you unpack it, and what you want to do with it in the end.

        If you want "the values" as "number", then you have to unpack them from the string. As long as you are dealing with four-byte numbers, or your Perl and the C program have the same interpretation of the long type, there will be no loss of accuracy.

        As for your questions about alignment etc., that is what Convert::Binary:C is set up to handle.

        The C struct has unsigned longs mostly. Each of these is 32 bytes, right?

        I would not bet on that. The C99 standard defines int as having the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range INT_MIN to INT_MAX as defined in the header <limits.h>)., so an int needs at least 16 bits. Other integer types, including unsigned long, are definied similary. C requires a minimum range, but no fixed number of bits. The implementation may choose bit sizes as required by the machine. So most C compilers on 32 bit systems actually define int as a 32 bit number, long int is typically 32 or 64 bit. But if you run on a 36 bit architecture without a 32 bit emulation layer, int should use 36 bit, long int may use 72 bit, and long long int could use 144 bit. Things get more complicated on 64 bit systems that attempt to support 32 bit software, see http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models. Note that UNICOS defines all basic integer types as 64 bit.

        See also http://stackoverflow.com/questions/589575/size-of-int-long-etc, http://en.wikipedia.org/wiki/C_data_types.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://996725]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2024-04-20 04:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found