perl vec 函数
vec EXPR,OFFSET,BITS
retval = vec(vector|expr, index|offset, bits);
返回由 OFFSET 指定的位域的值。即将 EXPR 中的字符串视为由宽度为 BITS 的元素组成的位向量,并将 OFFSET 指定的元素的值作为无符号整数返回。因此,BITS 指定为位向量中的每个元素保留的位数;它必须是 1 到 32 之间的 2 的幂(或者 64,如果您的平台支持的话),即1,2,4,8,16,32或64。
如果 BITS 为 8,则 "elements" 与输入字符串的字节序一致。
如果 BITS 为 16 或更多,则输入字符串的字节将被分组为大小为 BITS/8 的块,并且每个组都会转换为数字,就像 pack/unpack 具有大端格式 n/N 一样(对于 BITS== 也类似) 64)。详细信息请参见 pack 。
如果位为 4 或更少,则字符串被分解为字节,然后每个字节的位被分解为 8/BITS 组。字节的位以小端方式编号,如0x01、0x02、0x04、0x08、0x10、0x20、0x40、0x80。例如将单个输入字节 chr(0x36) 分成两组会得到一个列表 (0x6, 0x3);将其分成 4 组得到 (0x2, 0x1, 0x3, 0x0)。
vec 也可以被分配给,在这种情况下,需要括号来为表达式提供正确的优先级,如
vec($image, $max_x * $x + $y, 8) = 3;
如果所选元素在字符串之外,则返回值 0。如果写入字符串末尾的元素,Perl 将首先用足够多的零字节扩展字符串。尝试注销字符串的开头(即负 OFFSET)是错误的。
如果字符串恰好在内部编码为 UTF-8(因此设置了 UTF8 标志),vec 会尝试将其转换为使用每个字符一字节的内部表示形式。但是,如果字符串包含值为 256 或更高的字符,则会发生致命错误。
个人理解:调用vec,将EXPR按BITS分成N段,取对应的OFFSET这一段来操作。
使用 vec 创建的字符串也可以使用逻辑运算符 | 、& 、^ 和 ~ 进行操作。当两个操作数都是字符串时,这些运算符将假设需要位向量运算。参见 "Bitwise String Operators" in perlop。
vec函数是Perl语言中一个非常有用的函数,它可以将字符串转化为位向量,并进行各种灵活的位操作。通过设置不同的参数,可以实现位向量的转化、替换、数值计算和比较等功能。掌握vec函数的使用方法,可以更好地处理和操作位向量,提高编程效率和代码的可读性。
示例代码1
my $vec = '';
say 'Orig Len of $vec: ',length($vec);
vec($vec, 3, 4) = 1; # bits 0 to 3
vec($vec, 7, 4) = 10; # bits 4 to 7
vec($vec, 11, 4) = 9; # bits 8 to 11
vec($vec, 15, 4) = 15; # bits 12 to 15
say 'New Len of $vec: ',length($vec);
# As there are 4 bits per number this can
# be decoded by unpack() as a hex number
print("Has a created a string of nybbles, in bin: ", unpack("b*", $vec), "\n");
print("Has a created a string of nybbles, in hex: ", unpack("h*", $vec), "\n");
my $upk=unpack("b*", $vec);
say 'Len of $vec: ', length($upk);
>
Orig Len of $vec: 0
New Len of $vec: 8
Has a created a string of nybbles, in bin: 0000000000001000000000000000010100000000000010010000000000001111
Has a created a string of nybbles, in hex: 0001000a0009000f
Len of $vec: 64
示例代码2
my ($bstr,$ofs)=('',0);
for my $num (0,5,5,6,2,7,12,6){
vec($bstr,$ofs++,4)=$num;
}
say '$bstr:',$bstr,':',unpack("B32",$bstr),':',unpack('N*',$bstr);
>
$bstr:Perl:01010000011001010111001001101100:1348825708
示例代码3
my ($bar,$s1,$s2) = ('Perl',0,'');
#say $bar;
foreach(split(//,$bar)){
$s1+=ord($_);
$s2.=sprintf("%08b",ord);
}
printf "$bar num sum:%d,str sum:%s\n",$s1,$s2;
printf "Hex Value for Sum2:%#X\n",oct("0b$s2");
>
Perl num sum:403,str sum:01010000011001010111001001101100
Hex Value for Sum2:0X5065726C
示例代码4
# 16进制数字转为二进制数字
my $hexdigit = 0xB;
my $data;
vec($data, 0, 8) = $hexdigit;
say '=' x 19;
for(my $x=0;$x < 8;$x++) {
say "$x:",vec($data,$x,1);
}
say '=' x 19;
for(my $x=3;$x>=0;$x--){
say "$x:",vec($data, $x, 1);
}
say '=' x 19;
my $cnuns='CbcF.';
say unpack("b*",$cnuns);
say unpack("h*",$cnuns);
say 'length of $cnuns:',length($cnuns);
say vec($cnuns, 1, 8); #第2个元素:b
say vec($cnuns, 2, 4); #第2个元素b(0b01100010)的前半字节[小端](0b0010)
>
===================
0:1
1:1
2:0
3:1
4:0
5:0
6:0
7:0
===================
3:1
2:0
1:1
0:1
===================
1100001001000110110001100110001001110100
34263664e2
length of $cnuns:5
98
2
示例代码5
#program perlV4,p872
my @bits=(0,0,1,0, 1,0,1,0, 1,1,0,0, 0,0,1,0);
my ($bstr,$ost) = ('',0);
for my $bit (@bits) {
vec($bstr, $ost++, 1) = $bit;
}
say '$bstr: ',$bstr; #'TC','0x54,0x43'
say '-' x 9;
my $bstr2=pack("b*", join(q(), @bits));
say '$bstr2(b*): ',$bstr2; #TC
my $bstr3=pack("B*", join(q(), @bits));
say '$bstr3(B*): ',$bstr3;
say '-' x 9; #*
########
my $bitf;
vec($bitf,0,1)=1;
vec($bitf,1,4)=8; #8=0b1000,bits<=4,use little-endian
for(my $x=0;$x < 8;$x++) {
say "$x:",vec($bitf,$x,1);
}
say 'Len of $bitf:',length($bitf);
# another way to print out a bit field
print unpack("b*", $bitf), "\n";
>
$bstr: TC
---------
$bstr2(b*): TC
$bstr3(B*): *
---------
0:1
1:0
2:0
3:0
4:0
5:0
6:0
7:1
Len of $bitf:1
10000001
示例代码6
以下代码将构建一个 ASCII 字符串 'PerlPerlPerl'。注释显示每个步骤后的字符串。请注意,此代码在大端或小端机器上的工作方式相同。
my $foo = '';
vec($foo, 0, 32) = 0x5065726C; # 'Perl'
# $foo eq "Perl" eq "\x50\x65\x72\x6C",32 位
print vec($foo, 0, 8); # 打印 80 == 0x50 == ord('P')
vec($foo, 2, 16) = 0x5065; # 'PerlPe'
vec($foo, 3, 16) = 0x726C; # 'PerlPerl'
vec($foo, 8, 8) = 0x50; # 'PerlPerlP'
vec($foo, 9, 8) = 0x65; # 'PerlPerlPe'
vec($foo, 20, 4) = 2; # 'PerlPerlPe' . "\x02"
vec($foo, 21, 4) = 7; # 'PerlPerlPer','r' 是 "\x72"
vec($foo, 45, 2) = 3; # 'PerlPerlPer' . "\x0c"
vec($foo, 93, 1) = 1; # 'PerlPerlPer' . "\x2c"
vec($foo, 94, 1) = 1; # 'PerlPerlPerl',"l" 是 "\x6c"
要将位向量转换为字符串或0和1的列表,请使用以下命令:
my $bits = unpack("b*", $vector);
my @bits = split(//, unpack("b*", $vector));
如果知道确切的位长度,则可以使用它来代替 * 。
参考文档
perlfunc#vec-en
perlfunc#vec-cn
四位半字节(nybble)
端(字节)序
retval = vec(vector|expr, index|offset, bits);
返回由 OFFSET 指定的位域的值。即将 EXPR 中的字符串视为由宽度为 BITS 的元素组成的位向量,并将 OFFSET 指定的元素的值作为无符号整数返回。因此,BITS 指定为位向量中的每个元素保留的位数;它必须是 1 到 32 之间的 2 的幂(或者 64,如果您的平台支持的话),即1,2,4,8,16,32或64。
如果 BITS 为 8,则 "elements" 与输入字符串的字节序一致。
如果 BITS 为 16 或更多,则输入字符串的字节将被分组为大小为 BITS/8 的块,并且每个组都会转换为数字,就像 pack/unpack 具有大端格式 n/N 一样(对于 BITS== 也类似) 64)。详细信息请参见 pack 。
如果位为 4 或更少,则字符串被分解为字节,然后每个字节的位被分解为 8/BITS 组。字节的位以小端方式编号,如0x01、0x02、0x04、0x08、0x10、0x20、0x40、0x80。例如将单个输入字节 chr(0x36) 分成两组会得到一个列表 (0x6, 0x3);将其分成 4 组得到 (0x2, 0x1, 0x3, 0x0)。
vec 也可以被分配给,在这种情况下,需要括号来为表达式提供正确的优先级,如
vec($image, $max_x * $x + $y, 8) = 3;
如果所选元素在字符串之外,则返回值 0。如果写入字符串末尾的元素,Perl 将首先用足够多的零字节扩展字符串。尝试注销字符串的开头(即负 OFFSET)是错误的。
如果字符串恰好在内部编码为 UTF-8(因此设置了 UTF8 标志),vec 会尝试将其转换为使用每个字符一字节的内部表示形式。但是,如果字符串包含值为 256 或更高的字符,则会发生致命错误。
个人理解:调用vec,将EXPR按BITS分成N段,取对应的OFFSET这一段来操作。
使用 vec 创建的字符串也可以使用逻辑运算符 | 、& 、^ 和 ~ 进行操作。当两个操作数都是字符串时,这些运算符将假设需要位向量运算。参见 "Bitwise String Operators" in perlop。
vec函数是Perl语言中一个非常有用的函数,它可以将字符串转化为位向量,并进行各种灵活的位操作。通过设置不同的参数,可以实现位向量的转化、替换、数值计算和比较等功能。掌握vec函数的使用方法,可以更好地处理和操作位向量,提高编程效率和代码的可读性。
示例代码1
my $vec = '';
say 'Orig Len of $vec: ',length($vec);
vec($vec, 3, 4) = 1; # bits 0 to 3
vec($vec, 7, 4) = 10; # bits 4 to 7
vec($vec, 11, 4) = 9; # bits 8 to 11
vec($vec, 15, 4) = 15; # bits 12 to 15
say 'New Len of $vec: ',length($vec);
# As there are 4 bits per number this can
# be decoded by unpack() as a hex number
print("Has a created a string of nybbles, in bin: ", unpack("b*", $vec), "\n");
print("Has a created a string of nybbles, in hex: ", unpack("h*", $vec), "\n");
my $upk=unpack("b*", $vec);
say 'Len of $vec: ', length($upk);
>
Orig Len of $vec: 0
New Len of $vec: 8
Has a created a string of nybbles, in bin: 0000000000001000000000000000010100000000000010010000000000001111
Has a created a string of nybbles, in hex: 0001000a0009000f
Len of $vec: 64
示例代码2
my ($bstr,$ofs)=('',0);
for my $num (0,5,5,6,2,7,12,6){
vec($bstr,$ofs++,4)=$num;
}
say '$bstr:',$bstr,':',unpack("B32",$bstr),':',unpack('N*',$bstr);
>
$bstr:Perl:01010000011001010111001001101100:1348825708
示例代码3
my ($bar,$s1,$s2) = ('Perl',0,'');
#say $bar;
foreach(split(//,$bar)){
$s1+=ord($_);
$s2.=sprintf("%08b",ord);
}
printf "$bar num sum:%d,str sum:%s\n",$s1,$s2;
printf "Hex Value for Sum2:%#X\n",oct("0b$s2");
>
Perl num sum:403,str sum:01010000011001010111001001101100
Hex Value for Sum2:0X5065726C
示例代码4
# 16进制数字转为二进制数字
my $hexdigit = 0xB;
my $data;
vec($data, 0, 8) = $hexdigit;
say '=' x 19;
for(my $x=0;$x < 8;$x++) {
say "$x:",vec($data,$x,1);
}
say '=' x 19;
for(my $x=3;$x>=0;$x--){
say "$x:",vec($data, $x, 1);
}
say '=' x 19;
my $cnuns='CbcF.';
say unpack("b*",$cnuns);
say unpack("h*",$cnuns);
say 'length of $cnuns:',length($cnuns);
say vec($cnuns, 1, 8); #第2个元素:b
say vec($cnuns, 2, 4); #第2个元素b(0b01100010)的前半字节[小端](0b0010)
>
===================
0:1
1:1
2:0
3:1
4:0
5:0
6:0
7:0
===================
3:1
2:0
1:1
0:1
===================
1100001001000110110001100110001001110100
34263664e2
length of $cnuns:5
98
2
示例代码5
#program perlV4,p872
my @bits=(0,0,1,0, 1,0,1,0, 1,1,0,0, 0,0,1,0);
my ($bstr,$ost) = ('',0);
for my $bit (@bits) {
vec($bstr, $ost++, 1) = $bit;
}
say '$bstr: ',$bstr; #'TC','0x54,0x43'
say '-' x 9;
my $bstr2=pack("b*", join(q(), @bits));
say '$bstr2(b*): ',$bstr2; #TC
my $bstr3=pack("B*", join(q(), @bits));
say '$bstr3(B*): ',$bstr3;
say '-' x 9; #*
########
my $bitf;
vec($bitf,0,1)=1;
vec($bitf,1,4)=8; #8=0b1000,bits<=4,use little-endian
for(my $x=0;$x < 8;$x++) {
say "$x:",vec($bitf,$x,1);
}
say 'Len of $bitf:',length($bitf);
# another way to print out a bit field
print unpack("b*", $bitf), "\n";
>
$bstr: TC
---------
$bstr2(b*): TC
$bstr3(B*): *
---------
0:1
1:0
2:0
3:0
4:0
5:0
6:0
7:1
Len of $bitf:1
10000001
示例代码6
以下代码将构建一个 ASCII 字符串 'PerlPerlPerl'。注释显示每个步骤后的字符串。请注意,此代码在大端或小端机器上的工作方式相同。
my $foo = '';
vec($foo, 0, 32) = 0x5065726C; # 'Perl'
# $foo eq "Perl" eq "\x50\x65\x72\x6C",32 位
print vec($foo, 0, 8); # 打印 80 == 0x50 == ord('P')
vec($foo, 2, 16) = 0x5065; # 'PerlPe'
vec($foo, 3, 16) = 0x726C; # 'PerlPerl'
vec($foo, 8, 8) = 0x50; # 'PerlPerlP'
vec($foo, 9, 8) = 0x65; # 'PerlPerlPe'
vec($foo, 20, 4) = 2; # 'PerlPerlPe' . "\x02"
vec($foo, 21, 4) = 7; # 'PerlPerlPer','r' 是 "\x72"
vec($foo, 45, 2) = 3; # 'PerlPerlPer' . "\x0c"
vec($foo, 93, 1) = 1; # 'PerlPerlPer' . "\x2c"
vec($foo, 94, 1) = 1; # 'PerlPerlPerl',"l" 是 "\x6c"
要将位向量转换为字符串或0和1的列表,请使用以下命令:
my $bits = unpack("b*", $vector);
my @bits = split(//, unpack("b*", $vector));
如果知道确切的位长度,则可以使用它来代替 * 。
参考文档
perlfunc#vec-en
perlfunc#vec-cn
四位半字节(nybble)
端(字节)序