php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #78188 Improve unpack doc, explain why it's a 1 indexed array, etc.
Submitted: 2019-06-20 13:57 UTC Modified: 2019-06-21 12:29 UTC
From: girgias@php.net Assigned:
Status: Open Package: Unknown/Other Function
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
 [2019-06-20 13:57 UTC] girgias@php.net
Description:
------------
Currently unpack returns an array which starts with index 1.
This makes it unusable with list() directly as list() only works with 0 indexed arrays so to destructure an unpack array it first needs to go through array_values().

As this is a BC break I'm marking this Feature Request for next Major.

Sidenote, I tried to understand how PHP implements unpack but I'm confused as to how and when the array is returned from the function, if anyone can point me to some up to date documentation about the Zend engine that covers this bit that would be great as currently, phpinternalsbook does not cover Arrays in PHP 7

This may be partially related to #54734


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-06-20 14:34 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2019-06-20 14:34 UTC] requinix@php.net
> This makes it unusable with list()
If this is the main reason for your request then what if I told you that you can easily skip the first element?

  list(, $A, $B) = unpack("c2", "\x41\x42");


That aside, the behavior is related to how unpack handles a named repeated argument:

  <?php
  $binarydata = "\x04\x00\xa0\x00";
  $array = unpack("c2chars/nint", $binarydata);
  print_r($array);
  ?>

  Array
  (
    [chars1] => 4
    [chars2] => 0
    [int] => 40960
  )

Note that PHP starts with "chars1". When an argument is unnamed PHP follows the same process and forces it to be numbered, but without the name it results in the string "1" - which is a number and so forced to the integer 1 when used as an array key.


> how and when the array is returned from the function,
Documentation I don't have, but perhaps the missing link for you is the magic "return_value" variable. That's where return values from functions go, and unpack() uses it like

  array_init(return_value);

(to initialize an empty array) and

  zend_array_destroy(Z_ARR_P(return_value));
  RETURN_FALSE;

(RETURN_FALSE is a macro to set return_value=false and return) and

  add_assoc_stringl(return_value, n, &input[inputpos], len);
 [2019-06-21 12:29 UTC] girgias@php.net
-Summary: Make unpack return a 0 indexed array instead of a 1 indexed array +Summary: Improve unpack doc, explain why it's a 1 indexed array, etc. -Status: Feedback +Status: Open -Type: Feature/Change Request +Type: Documentation Problem -PHP Version: Next Major Version +PHP Version: Irrelevant
 [2019-06-21 12:29 UTC] girgias@php.net
> If this is the main reason for your request then what if I told you that you can easily skip the first element?
It is kind of the main reason but mostly I didn't get why it would start at 1 instead of 0. The implementation explanation makes sense.

However just to confirm if all unpack formats are named then it does behave as a 0 indexed array, right?
So in a way its the behavior of numerical string keys as array keys which is jumping out.

I'll change that to a doc bug as the named keys in the return array isn't documented


> [...] but perhaps the missing link for you is the magic "return_value" variable.
> That's where return values from functions go, and unpack() uses it like

That was indeed the missing link. :)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Oct 12 10:01:28 2024 UTC