http://qs1969.pair.com?node_id=953601

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

Hi. I am a fairly experienced Perl amateur, or so I thought. I've been whipping things up in Perl for some 10+ years, but I've never gotten very deep down into the nuts and bolts until fairly recently. Despite being a onetime computer science major as an undergrad (before turning the dark side and becoming a historian), I struggle with computer-sciencey concepts, so that might be part of my problem here.

Anyway, I am trying to learn about pack and unpack and bitwise operations and such. And I have run into some behavior that seems very odd and I can't explain it. I am using the latest release of ActivePerl on a Win32 (WinXP) system.

use strict; use warnings 'all'; my $i = 0; # This should be zero! I want 0b00000000! my $b = unpack("B*", $i); print $b;

The output I get is:

00110000

In other words, what I am getting instead of zero (i.e. 0b00000000, 0x00, NUL, the real zero) is 0b00110000, or 0x48 -- the ASCII character 0. This isn't what I want. It doesn't matter how I write the number. Whether I code $i = 0 or 0x00 or 0b00000000 -- I keep getting the character 0.

If, on the other hand, I code:

printf("%08b", 0);

I properly get:

00000000

Why is this happening? Why is unpack interpreting my 0 as a character or string? Is this the proper behavior for Perl, or is it some quirk or bug of this distribution or system? Or am I just doing something wrong, or misunderstanding what is happening here? Is there any way to stop it?

Replies are listed 'Best First'.
Re: ActivePerl on Win32 storing integers as strings?
by BrowserUk (Patriarch) on Feb 14, 2012 at 04:43 UTC

    Does this clarify things?

    print unpack 'B*', pack 'C', 0;; 00000000 print unpack 'B*', pack 'v', 0;; 0000000000000000 print unpack 'B*', pack 'V', 0;; 00000000000000000000000000000000

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      Thanks. I think so. So the issue is that unpack takes a string as an argument (which I now see on the description in perlfunc), so it's unpack itself that forces the number to be interpreted as a string? Packing it explicitly as an integer gives it an integer to unpack -- though pack, according to perlfunc, also produces a string. I guess I just lack a basic understanding about how Perl stores data. My understanding of data types is essentially C-centric (char or int or short or string).

        You're almost there.

        As you say, unpack takes a string as its argument. If you supply an integer, then Perl quietly converts it to a (human readable) string for you, just as it does when do print 0; It 'ascii-ises' the number. In C terms, Perl does an itoa() on it.

        Conversely, when you pack the number, the string returned contains the machine readable, binary representation embedded within a string. In C terms, it is like doing:

        int i = 0; printf( "%s", (char*)&i );

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

Re: ActivePerl on Win32 storing integers as strings?
by LonelyPilgrim (Beadle) on Feb 14, 2012 at 04:19 UTC
    This is just the simplest example I could post, by the way. I get similarly bizarre and more troubling behavior when I attempt to unpack longer integers. unpack interprets 65535 as, for example, 36 35 35 33 35 -- a string of the characters 65535.