当前位置: 首页 > 知识库问答 >
问题:

PHP unpack()的意外行为

华升
2023-03-14
$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'afoo/abar/abaz' , $x );
print_r( $y );
$x = sprintf( "foo\x00bar\x00baz" );
$y = unpack( 'a*foo/a*bar/a*baz' , $x );
print_r( $y );
Array
(
    [foo] => f
    [bar] => o
    [baz] => o
)
Array
(
    [foo] => foobarbaz
    [bar] => 
    [baz] => 
)

请注意,NULL字节始终存在,您可以使用hexload检查它。

Array
(
    [foo] => foo
    [bar] => bar
    [baz] => baz
)

我知道我可以使用explode获得类似的结果。我不是在问其他选择,我只是想了解a格式字符(如doc所说的“NUL填充字符串”)背后的逻辑。

“NULL”值在哪里涉及到所有这些?

共有1个答案

施权
2023-03-14

"NULL"值在这一切中的作用是什么?"

无处

我很确定PHP pack()/unpack()的留档需要更新。基本上,无论你在哪里看到它引用NULL终止的字符串,文档都是从Perl版本的代码中获取的,并不反映PHP中正在发生的事情。

基本上,Perl有C风格的字符串,可以以null结尾,让您知道字符串的结尾在哪里。在PHP中,没有空字符的概念。例如

$test1 = "Test".NULL."ing";
$test2 = "Testing";

if(strcmp($test1, $test2) == 0){
    echo "The strings are the same";
}
else{
    echo "They are different.";
}

将打印“字符串相同”。

顺便说一句:“foo\x00bar\x00baz”

可能没有做你认为它在做的事情。它不会在foo-bar和bar-baz之间的字符串中放置“NULL”字符,因为没有NULL字符。取而代之的是字符“0”,它恰好在大多数字符集中没有打印出来,但作为一个字符没有特殊意义。

我知道您提到使用explode而不是unpack,但如果您知道字符串长度,则可以使用:

unpack( 'a3foo/a3bar/a3baz' , $binarydata);

赛勒斯写道:

“空字节”是指值为0的字节:

我不确定字符串“foo\x00bar\x00baz”是从哪里来的,但是:

i)它必须来自支持由零表示的NULL字符的语言。PHP不支持NULL字符,如果你调用pack("A*A*A*","foo","bar","baz");它不会生成包含零的字符串。

ii)解包的PHP版本不支持空字符(因为PHP不支持空字符),并将十六进制值为0的字符视为另一个字符。例如

function strToHex($string){
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}

$binarydata = "foo\x00bar\x00baz";

echo "binarydata is ";

var_dump($binarydata);
$y = unpack( 'a3foo/a3bar/a3baz' , $binarydata);
var_dump( $y );

echo strToHex($y['foo'])."\r\n";
echo strToHex($y['bar'])."\r\n";
echo strToHex($y['baz'])."\r\n";

将输出:

binarydata is string(11) "foobarbaz"
array(3) {
  ["foo"]=>
  string(3) "foo"
  ["bar"]=>
  string(3) "ba"
  ["baz"]=>
  string(3) "rb"
}
666f6f
06261
72062

i、 e.它提取前三个字符,即值0x66、0x6f、0x6f。然后提取接下来的三个字符,即0x0、0x62、0x61。最后,它提取值0x72、0x0、0x62。

 类似资料:
  • 问题内容: 前一阵子,在使用Class.getMethod和自动装箱时,我遇到了类似的问题,因此在自己的查找算法中实现它很有意义。但是,真正让我感到困惑的是,以下两种方法也不起作用: String.class实现了Serializable接口,我确实希望它包含在lookup方法中。 我也必须在自己的查找算法中考虑这一点吗? 编辑 :我确实读过Javadoc, 所以让我强调一下问题的第二部分 :如果

  • 我是Python的新手,我对Python处理空对象的方式有点困惑。 考虑这段代码; 我得到了这段代码的以下输出。 我假设由{}初始化的对象是有效对象。为什么Python不那样对待它?为什么要得到diff If条件的diff输出? 在C++中,当我说 如果obj不是NULL,它将进入IF块(不管它是垃圾值还是其他) 但当我翻译成Python时也是一样的。 为什么?我读到Python将{}计算为fal

  • 我有以下输入字符串: 这里有各种各样的错误:标题前面有“。”应该是ID后面的分隔符。作者姓名的最后两个字符出现在日期字段中,实际日期丢失。 我怎样才能纠正这些问题?

  • 问题内容: 我有以下代码: 我希望它返回“ 05/20/2012”,但它返回“ 04/20/2012” 这对我来说毫无意义-有人可以帮助我了解发生了什么以及如何获得正确的响应吗? 感谢您的关注! 问题答案: 从零开始。如和 尝试

  • 我使用GNU gcc(4.8.1429)为ARM(ATsam4LC4B:cortexM4 core,256K flash)构建了一个简单的应用程序: 在0x3F000(链接器选项-Ttext=0x3F000)加载并初始化, 在0处复制自身(镜像) 使用assembly跳转到镜像重置处理程序()(接近0) 镜像应用程序开始按预期运行 当达到mirror main()调用的闪存位置(闪存位置0x532

  • 问题内容: 我今天在go代码中遇到了奇怪的行为:当我追加到in循环中,然后尝试根据循环的结果创建new时,最后一个重写了previous 。 在这个特殊的例子这意味着 ,和切片的最后一个元素都没有,和分别,但是......始终! 第二个示例- 行为符合预期。 链接至play.golang:https : //play.golang.org/p/INADVS3Ats 经过一番阅读,挖掘和实验后,我发