PHP - unzip as unsigned int

How to convert binary string to unsigned int?

I do

$id = unpack('V', substr($dir, $mid * 12, 4))[1]; echo $id . '<br/>'; 

Where V , according to the documentation,

unsigned long (always 32 bits, low byte order)

And he prints -992455690. How is this possible?

Update: found in the documentation:

Note that PHP internally saves integral values ​​as signed. If you unpack a large unsigned long one and it is the same size as the internal PHP values, the result will be negative even if unsigned unpacking was specified.

So now the question is, what is the point of format V , if it is identical to the signed version, except for creating confusion?

+6
source share
2 answers

Unfortunately, for 32-bit PHP distributions, as it seems to you, and where the internal consistency of the machine is a "small" version, the answer seems to be: it makes little sense to have a separate V format as opposed to l !

For 64-bit PHP distributions, the V format allows the developer to extract useful information by decoding binary strings encoded in the system / language, which allows you to access 4-byte values, but your question then goes up to be 'What is the P format for 64 -discharge machines if it is identical to the signed version. '

In addition, I would suggest that the format used also provides useful information to any reading developer about the intention of the code, because (if it is converted back to a binary string using pack() ), the binary representation of the negative number will be the same as the original unsigned number . If the developer knows that they will process integers in the extreme range of acceptable values, then they should know that in order to (manually) correctly handle cases of overflow / underflow.

In addition, and it may be worth noting that the manual for pack , which gives these codes, gives only one code for formats of signed values ​​that are always machine byte order, while formats without signed values ​​allow you to specify a specific byte order in addition to the order cars. If, therefore, you would like to decode the signed 16-bit value originally stored on ARM (big-endian) in a 32-bit php distribution on intel (little-endian) without manipulating the byte order, you will have to first decode as unsigned 16 -bit big-endian, and then manually subtract 2 ^ 15 if the resulting number exceeds this value.

+2
source

I think unpacking works for you. If it does not work, try the code below. Since this is a small sequence number, I use ord to compute the ascii of each byte of the 32-bit int var, then it computes the value of int.

 $chars = substr($dir, $mid * 12, 4); return ord($chars[0]) + ord($chars[1]) << 8 + ord($chars[2]) << 16 + ord($chars[3]) << 24. 
+1
source

All Articles