Hi,
ich möchte lange Binärstrings mit ...
$ergebnis_array = unpack( 'N*', $langer_binaerstring); // Big. Endian
$ergebnis_array = unpack( 'V*', $langer_binaerstring); // Lit. Endian
... in 32-Bit Integer zerlegen und umwandeln. Dabei bin ich auf folgendes Problem gestossen:
In der Doku http://de3.php.net/manual/de/function.pack.php heisst es zu den pack() Parametern 'N' und 'V':
N vorzeichenloser Long-Typ (immer 32 Bit, Byte-Folge Big Endian)
V vorzeichenloser Long-Typ (immer 32 Bit, Byte-Folge Little Endian)
(im engl. Handbuch steht das gleiche)
Bei beiden Parametern soll pack() demnach den 32-Bit Übergabewert als positiven Integer interpretieren. Anders formuliert: das Ergebnis von pack() dürfte niemals negativ sein.
Nach allen Test die ich gemacht habe ist das aber falsch. Bei Verwendung von Paramter 'N' gibt Bit Nr. 31 (also das 32ste Bit von rechts) an, ob die Zahl positiv oder negativ ist. Also ein typisches Zweierkomplement.
Wenn ich nun keinen grossen Denkfehler gemacht habe, das ist entweder die Dokumentation oder der PHP-Interpreter fehlerhaft.
Weiss jemand, ob die Doku falsch ist oder der Interpreter (dritte Variante siehe direkt hier drüber)? Ich Frage deshalb, weil ich sicher sein will dass mein Programm auch in ein paar Jahren noch läuft. Wenn es ein Interpreterfehler ist, muss ich damit rechnen, das der Fehler bei der nächsten Version behoben ist.
Andere Parameter von pack() für 32-Bit-Zahlen ('I','L') helfen mir nicht weiter - ich möchte unbedingt maschinen- bzw. prozessorunabhängig sein.
Unten noch ein kurzes Programm, dass das Verhalten von pack() demonstriert.
Vielen Dank, Gerold
PS: ich schaue mind. 2 Tage nach Antworten rein.
#!/usr/bin/php
<?php
// Diese Programm laeuft in Unix Shellumgebung und testet die PHP Funktion
// pack() mit dem Parameter 'N' bzw. 'V'.
function unpack_test($B1, $B2, $B3, $B4)
{
// Unsere 4 Bytes mit Parameter 'N' und 'V' an unpack() uebergeben und das
// Ergebnis in $$unpack_N bzw. $unpack_V speichern.
$unpack_N = unpack( 'N', $B1.$B2.$B3.$B4); // Reihenfolge der Bytes 1,2.3,4
$unpack_V = unpack( 'V', $B4.$B3.$B2.$B1); // Reihenfolge der Bytes 4,3,2,1
// Vorbereitung der Ausgabe: Strings zur Binaerdarstellung (mit 1en und 0en)
// generieren. Die Strings werden unten mit echo ausgegeben.
$printf_format = '%1$08b %2$08b %3$08b %4$08b';
$binaer_str_N = sprintf($printf_format, ord($B1), ord($B2),ord($B3), ord($B4) );
$binaer_str_V = sprintf($printf_format, ord($B4), ord($B3),ord($B2), ord($B1) );
// Ausgabe der Daten von unpack()
echo "$binaer_str_N entspr. in unpack_N $unpack_N[1] \n";
// echo "$binaer_str_V entspr. in unpack_V $unpack_V[1] \n";
// Wenn die Zeile fuer die Ausgabe der "V Werte" direkt hier drueber einkom-
// mentiert wird, wird die Ausgabe etwas unuebersichtlich.
}
// Aufruf der Funktion unpack_test() mit verschiedenen Uebergabewerten.
echo "Die kleinsten negativen Zahlen ... \n";
unpack_test( chr(128), chr( 0), chr( 0), chr( 0) );
unpack_test( chr(128), chr( 0), chr( 0), chr( 1) );
unpack_test( chr(128), chr( 0), chr( 0), chr( 2) );
unpack_test( chr(128), chr( 0), chr( 0), chr( 3) );
echo "Die groessten negativen Zahlen ... \n";
unpack_test( chr(255), chr(255), chr(255), chr(252) );
unpack_test( chr(255), chr(255), chr(255), chr(253) );
unpack_test( chr(255), chr(255), chr(255), chr(254) );
unpack_test( chr(255), chr(255), chr(255), chr(255) );
echo "Die kleinsten positiven Zahlen ... \n";
unpack_test( chr( 0), chr( 0), chr( 0), chr( 0) );
unpack_test( chr( 0), chr( 0), chr( 0), chr( 1) );
unpack_test( chr( 0), chr( 0), chr( 0), chr( 2) );
unpack_test( chr( 0), chr( 0), chr( 0), chr( 3) );
echo "Die groessten positiven Zahlen ... \n";
unpack_test( chr(127), chr(255), chr(255), chr(252) );
unpack_test( chr(127), chr(255), chr(255), chr(253) );
unpack_test( chr(127), chr(255), chr(255), chr(254) );
unpack_test( chr(127), chr(255), chr(255), chr(255) );
echo "... \n";
die(); // Keine Ausgabe hinter "?>"
?>