#!/opt/perl5.004/bin/perl # Around perl5.002 (I'm guessing perl5.0), they added the ability to # ~negate strings. Previous perl would int() a string first (usually # resulting in negating 0). In perl5.004 this somehow introduced a # bug with normal integer negations. If perl had string and integer # versions of a variable it would choose which to use based on the # history of the variable. As far as I can tell it would use whatever # value it was last used as, unless the MSB was high in the integer, # or if int() had ever been called on it. That's weird. # Anyways, this was a problem because when you print an integer it # stringizes it and saves the string version with the integer - then you # end up using the string when you try to negate it. In perl5.004_03 # they must have figured this out (it was in pre-release when I found this), # because it seems that they now only negate the string version if they # don't have an integer version. $mask=0x80000000; # Set mask with MSB=1 "$mask"; # Stringize mask (cached in the variables history) print ~$mask, "\n"; # NEGATES INT $mask=0x40000000; # Now try with MSB=0 "$mask"; print ~$mask, "\n"; # NEGATES *STRING* VALUE <-- BUG!!! $mask=0x40000000; # This works print ~$mask, "\n"; # NEGATES INT $mask=0x40000000; "$mask"; $mask+1; # We use it as an int again print ~$mask, "\n"; # NEGATES INT $mask=0x40000000; # This is not int($mask); # This permanently clobbers mask as an int? "$mask"; print ~$mask, "\n"; # NEGATES INT ################################################## # # Here's another manifestation of the bug # $a=-53; printf "HEY: $a %d %x\n",$a,$a; $a=$a & (~3); # This should recognize $a as unsigned from here out # But in perl5.002 it becomes some sort of string. printf "HEY: $a %d %x\n",$a,$a;