你能解释我从解包中得到的东西吗?

Rob*_*Rob 5 perl bits unpack pack

我对Perl相对缺乏经验,但我的问题是在获取数值的位时解压缩函数.例如:

my $bits = unpack("b*", 1);
print $bits;
Run Code Online (Sandbox Code Playgroud)

这导致打印10001100,其为十进制140.按相反的顺序,它是十进制的49.我试过的任何其他值似乎给出了不正确的位.

但是,当我通过pack运行$ bits时,它再次生成1.这里有什么我想念的吗?

当我认为我的问题得到解决时,我似乎得出了结论.也许我应该简单解释一下我正在尝试做什么.

我需要将一个可能大到24位长的整数值(可能大于一个字节)转换为位串.这可以使用@ikegami建议的解包和打包来完成,但我还需要找到一种方法将该位串转换回它的原始整数(不是它的字符串表示).

正如我所提到的,我对Perl相对缺乏经验,而且我一直在尝试没有成功.


我找到了似乎是最佳解决方案:

my $bits = sprintf("%032b", $num);
print "$bits\n";
my $orig = unpack("N", pack("B32", substr("0" x 32 . $bits, -32)));
print "$orig\n";
Run Code Online (Sandbox Code Playgroud)

goo*_*ide 6

这可能是显而易见的,但其他答案并没有明确指出:第二个参数unpack("b*", 1)是对字符串的类型转换"1",其ASCII值为31十六进制(首先是最重要的半字节).

相应的二进制文件将在您的输出中00110001反转,10001100因为您使用的是"b*"而不是"B*".这些对应于二进制表示的相反"endian"形式."Endian-ness"只是最重要的位是在二进制表示的开头还是结尾.


cjm*_*cjm 2

您正在尝试将整数转换为二进制,然后再转换回来。虽然您可以使用pack然后unpack来执行此操作,但更好的方法是使用sprintfprintf ,格式如下%b

my $int = 5;
my $bits = sprintf "%024b\n", $int;
print "$bits\n";
Run Code Online (Sandbox Code Playgroud)

要采用另一种方式(将 0 和 1 的字符串转换为整数),最好的方法是使用带前缀的oct0b函数:

my $orig = oct("0b$bits");
print "$orig\n";
Run Code Online (Sandbox Code Playgroud)

正如其他人所解释的,unpack需要一个字符串来解包,所以如果你有一个整数,你首先必须将pack它转换成一个字符串。该%b格式要求以整数开头。

如果您需要在字节上执行大量操作,并且速度至关重要,您可以构建一个查找表:

my @binary = map { sprintf '%08b', $_ } 0 .. 255;

print $binary[$int];  # Assuming $int is between 0 and 255
Run Code Online (Sandbox Code Playgroud)