Operasi Biner dan Bitwise di PHP



Baru-baru ini saya memperhatikan bahwa dalam berbagai proyek saya harus aktif menulis operasi bitwise di PHP. Ini adalah keterampilan yang sangat menarik dan berguna yang berguna dari membaca binari hingga meniru prosesor.



PHP memiliki banyak alat untuk membantu Anda memanipulasi data biner, tetapi saya ingin segera memperingatkan Anda: jika Anda menginginkan efisiensi tingkat super rendah, maka bahasa ini bukan untuk Anda.



Dan sekarang ke bisnis! Pada artikel ini, saya akan memberi tahu Anda banyak hal menarik tentang operasi bitwise, pemrosesan biner dan heksadesimal, yang akan berguna dalam bahasa APA PUN.





PHP



Saya suka PHP, jangan salah paham. Dan saya yakin bahasa ini akan berfungsi dengan baik dalam banyak kasus. Tetapi jika Anda membutuhkan efisiensi maksimum dalam memproses data biner, maka PHP tidak akan melakukannya.



Izinkan saya menjelaskan: Saya tidak berbicara tentang fakta bahwa aplikasi dapat mengonsumsi lima atau sepuluh megabyte lebih banyak, tetapi tentang mengalokasikan jumlah memori tertentu untuk menyimpan data dari jenis tertentu.



Menurut dokumentasi resmi tentang bilangan bulat , PHP mewakili nilai desimal, heksadesimal, oktal, dan biner menggunakan tipe bilangan bulat. Jadi tidak masalah data apa yang Anda taruh di sana, itu akan selalu berupa bilangan bulat.



Anda mungkin sudah tahu tentang ZVAL - ini adalah struktur C yang mewakili setiap variabel PHP. Ini memiliki bidang zend_long untuk mewakili semua angka . Bidang ini memiliki jenis lval



, yang ukurannya bergantung pada platform: pada platform 64-bit, bidang akan direpresentasikan sebagai nomor 64-bit , dan pada platform 32-bit, sebagai nomor 32-bit .



# zval stores every integer as a lval
typedef union _zend_value {
  zend_long lval;
  // ...
} zend_value;

# lval is a 32 or 64-bit integer
#ifdef ZEND_ENABLE_ZVAL_LONG64
 typedef int64_t zend_long;
 // ...
#else
 typedef int32_t zend_long;
 // ...
#endif

      
      





Intinya begini: tidak masalah jika Anda perlu menyimpan 0xff, 0xffff, 0xffffff, atau yang lainnya. Dalam PHP, semua nilai tersebut akan disimpan sepanjang ( lval ) dengan panjang 32 atau 64 bit.



Misalnya, saya baru-baru ini bereksperimen dengan meniru mikrokontroler. Dan sementara itu diperlukan untuk menangani konten memori dan operasi dengan benar, saya tidak memerlukan terlalu banyak efisiensi memori karena mesin hosting saya mengompensasi urutan biaya yang besarnya.



Tentu saja, semuanya berubah jika kita berbicara tentang ekstensi-C atau FFI, tetapi ini juga bukan tujuan saya. Saya berbicara tentang PHP murni.



Jadi ingat: ini berfungsi dan dapat berperilaku seperti yang Anda inginkan, tetapi dalam banyak kasus jenis akan membuang memori secara tidak efisien.



Pengenalan singkat tentang representasi data biner dan heksadesimal



Sebelum berbicara tentang bagaimana PHP menangani data biner, Anda harus terlebih dahulu berbicara tentang apa itu biner. Jika Anda merasa sudah mengetahui semua tentang ini, lanjutkan ke Bilangan Biner dan String di bab PHP .



Dalam matematika ada konsep "pondasi". Ini mendefinisikan bagaimana kita dapat merepresentasikan kuantitas dalam format yang berbeda. Orang biasanya menggunakan basis desimal (basis 10), yang memungkinkan kita untuk merepresentasikan angka apa pun dengan digit 0, 1, 2, 3, 4, 5, 6, 7, 8, dan 9.



Untuk memperjelas contoh selanjutnya, saya akan merujuk ke angka 20 sebagai "Desimal 20".



Bilangan biner (basis 2) dapat mewakili bilangan apa pun, tetapi hanya menggunakan dua digit: 0 dan 1.



Desimal 20 dalam biner terlihat seperti ini: 0b000 10100 . Anda tidak perlu mengubahnya sendiri ke bentuk yang sudah biasa, biarkan komputer melakukannya. ;)



Bilangan heksadesimal (basis 16) dapat mewakili bilangan apa pun menggunakan sepuluh digit 0, 1, 2, 3, 4, 5, 6, 7, 8 dan 9, serta enam karakter tambahan dari alfabet Latin: a, b, c , d, e dan f.



Desimal 20 dalam bentuk heksadesimal terlihat seperti ini: 0x14. Serahkan transformasi ke komputer, mereka ahli dalam hal ini!



Penting untuk dipahami bahwa bilangan dapat direpresentasikan dalam basis yang berbeda: biner (basis 2), oktal (basis 8), desimal (basis 10, biasanya), dan heksadesimal (basis 16).



Dalam PHP dan banyak bahasa lainnya, angka biner ditulis seperti yang lain, tetapi diawali dengan 0b : desimal 20 terlihat seperti 0b 00010100. Hexadecimal nomor yang diawali dengan 0x : desimal 20 terlihat seperti 0x 14.



Seperti yang Anda mungkin sudah tahu, komputer tidak menyimpan data literal ... Semuanya direpresentasikan dalam bentuk bilangan biner, nol, dan satu. Simbol, angka, huruf, instruksi - semuanya disajikan di basis 2. Huruf hanyalah konvensi urutan angka. Misalnya, huruf "a" adalah angka 97 di tabel ASCII.



Tetapi meskipun semuanya disimpan dalam biner, programmer paling nyaman membaca data dalam format heksadesimal. Mereka terlihat lebih baik seperti itu. Hanya melihat:



# string "abc"
'abc'

# binary form (bleh)
0b01100001 0b01100010 0b01100011

# hexadecimal form (such wow)
0x61 0x62 0x63

      
      





Meskipun format biner secara visual membutuhkan banyak ruang, data heksadesimal sangat mirip dengan representasi biner. Oleh karena itu, kami biasanya menggunakannya dalam pemrograman tingkat rendah.



Operasi transfer



Anda sudah familiar dengan konsep carry, tapi saya harus memperhatikannya agar kami bisa menggunakannya untuk berbagai alasan.



Dalam himpunan desimal, kita memiliki sepuluh digit terpisah untuk mewakili angka, dari 0 hingga 9. Tetapi ketika kita mencoba untuk merepresentasikan angka yang lebih besar dari sembilan, kita kehilangan digit! Dan di sini operasi carry diterapkan: kami mengawali angka dengan digit 1, dan menyetel ulang digit yang benar menjadi 0.



# decimal (base 10)
1 + 1 = 2
2 + 2 = 4
9 + 1 = 10 // <- Carry

      
      





Basis biner berperilaku sama, hanya saja dibatasi pada angka 0 dan 1.



# binary (base 2)
0 + 0  = 0
0 + 1  = 1
1 + 1  = 10 // <- Carry
1 + 10 = 11

      
      





Ini sama dengan basis heksadesimal, hanya saja jangkauannya jauh lebih luas.



# hexadecimal (base 16)
1 + 9  = a // no carry, a is in range
1 + a  = b
1 + f  = 10 // <- Carry
1 + 10 = 11

      
      





Seperti yang Anda pahami, operasi carry membutuhkan lebih banyak digit untuk mewakili angka tertentu. Hal ini memungkinkan kita untuk memahami betapa terbatasnya jenis data tertentu dan, karena disimpan di komputer, betapa terbatasnya representasi binernya.



Representasi data dalam memori komputer



Seperti yang saya sebutkan di atas, komputer menyimpan semuanya dalam format biner. Artinya, mereka hanya mengandung nol dan satu dalam memori.



Paling mudah untuk memvisualisasikan konsep ini sebagai tabel besar dengan satu baris dan banyak kolom (sebanyak yang dimungkinkan oleh kapasitas memori. Setiap kolom adalah bilangan biner (bit).



Representasi desimal 20 kita dalam tabel menggunakan 8 bit terlihat seperti ini:



Posisi (alamat) 0 satu 2 3 4 5 6 7
Sedikit 0 0 0 satu 0 satu 0 0


Integer 8-bit unsigned adalah angka yang dapat direpresentasikan menggunakan maksimal 8 angka biner. Artinya, 0b11111111 (255 desimal) akan menjadi bilangan 8-bit unsigned terbesar. Menambahkan 1 ke dalamnya akan membutuhkan penggunaan operasi carry, yang tidak lagi dapat direpresentasikan menggunakan jumlah digit yang sama.



Mengetahui hal ini, kita dapat dengan mudah mencari tahu mengapa ada begitu banyak representasi dalam memori untuk angka dan apakah itu: uint8 adalah bilangan bulat 8-bit unsigned (desimal 0-255), uint16 adalah bilangan bulat 16-bit unsigned (desimal 0-65535 ). Ada juga uint32, uint64 dan, secara teori, ada yang lebih tinggi.



Bilangan bulat bertanda, yang dapat mewakili nilai negatif, biasanya menggunakan bit terakhir untuk menentukan apakah nilainya positif (bit terakhir = 0) atau negatif (bit terakhir = 1). Seperti yang dapat Anda bayangkan, mereka memungkinkan Anda menyimpan nilai yang lebih kecil dalam jumlah memori yang sama. Rentang bilangan bulat 8-bit bertanda dari -128 hingga desimal 127.



Berikut adalah -20 desimal, yang direpresentasikan sebagai bilangan bulat 8-bit bertanda. Perhatikan bahwa bit pertama diatur (alamat 0, nilai 1), ini berarti angka negatif.



Posisi (alamat) 0 satu 2 3 4 5 6 7
Sedikit satu 0 0 satu 0 satu 0 0


Saya harap semuanya jelas sejauh ini. Pengenalan ini penting untuk memahami cara kerja komputer. Ingatlah hal ini, dan kemudian Anda akan selalu memahami cara kerja PHP di bawah tenda.



Aritmatika meluap



Representasi angka yang dipilih (8-bit, 16-bit) menentukan nilai minimum dan maksimum dari jangkauan. Ini semua tentang bagaimana angka disimpan dalam memori: menambahkan 1 ke digit biner 1 menghasilkan operasi carry, yaitu, Anda memerlukan bit lain sebagai awalan untuk angka saat ini. Karena format integer didefinisikan dengan sangat hati-hati, kami tidak dapat mengandalkan operasi carry di luar batas (sebenarnya mungkin, tetapi cukup gila).



Posisi (alamat) 0 satu 2 3 4 5 6 7
Sedikit satu satu satu satu satu satu satu 0


Di sini kita sangat dekat dengan batas 8-bit (255 desimal). Jika kita menambahkan satu, kita mendapatkan 255 desimal dalam biner:



Posisi (alamat) 0 satu 2 3 4 5 6 7
Sedikit satu satu satu satu satu satu satu satu


Semua bit ditetapkan! Menambahkan 1 akan membutuhkan operasi carry yang tidak akan mungkin dilakukan karena kita kehabisan bit, 8 bit sudah ditetapkan! Situasi ini disebut overflow , kami melampaui batas tertentu. Operasi biner 255 + 2 harus memberikan hasil 8-bit 1.



Posisi (alamat) 0 satu 2 3 4 5 6 7
Sedikit 0 0 0 0 0 0 0 satu


Perilaku ini tidak disengaja, nilai baru dihitung menggunakan aturan tertentu, yang tidak akan kami pertimbangkan di sini.



Bilangan biner dan string dalam PHP



Kembali ke PHP! Maaf atas penyimpangan besar ini, tapi menurut saya ini penting.



Saya harap Anda sudah memiliki potongan teka-teki di kepala Anda: bilangan biner, bagaimana mereka disimpan, apa yang melimpah, bagaimana PHP mewakili angka ...



Desimal 20, diwakili dalam PHP sebagai nilai integer, dapat memiliki dua representasi berbeda tergantung pada platformnya ... Pada platform x86 ini akan menjadi representasi 32-bit, pada x64 akan menjadi 64-bit, tetapi dalam kedua kasus akan ada tanda (artinya, nilainya bisa negatif). Kita tahu bahwa desimal 20 dapat masuk dalam ruang 8-bit, tetapi PHP memperlakukan bilangan desimal apa pun sebagai 32 atau 64 bit.



PHP juga memiliki string biner yang dapat diubah bolak-balik menggunakan fungsi pack () dan unpack () .



Di PHP, perbedaan utama antara string biner dan angka adalah string hanya berisi data, seperti buffer. Nilai bilangan bulat (biner dan tidak hanya) memungkinkan Anda melakukan operasi aritmatika dengan dirinya sendiri, tetapi juga nilai biner (bitwise) seperti AND, OR, XOR, dan NOT.



Biner: apa yang harus digunakan dalam PHP, angka atau string?



Kami biasanya menggunakan string biner untuk mengangkut data. Oleh karena itu, membaca file biner atau jaringan memerlukan pengemasan dan pembongkaran string biner.



Namun, operasi sebenarnya seperti OR dan XOR tidak dapat dilakukan dengan andal dengan string, jadi Anda perlu menggunakan angka.



Debugging nilai biner di PHP



Sekarang mari bersenang-senang dan bermain-main dengan beberapa kode PHP!



Pertama, saya akan menunjukkan kepada Anda bagaimana memvisualisasikan data. Kita harus memahami apa yang kita hadapi.



Debugging integer sangat, sangat mudah, kita bisa menggunakan fungsi sprintf () . Ini memiliki format yang sangat kuat dan akan membantu kita dengan cepat memahami nilai apa yang kita kerjakan.



Mari kita gambarkan desimal 20 dalam biner 8-bit dan heksadesimal 1-byte:



<?php
// Decimal 20
$n = 20;

echo sprintf('%08b', $n) . "\n";
echo sprintf('%02X', $n) . "\n";

// Output:
00010100
14

      
      





Format tersebut %08b



mengeluarkan variabel dalam $n



representasi biner ( b



) dengan delapan digit ( 08



).



Format tersebut %02X



menampilkan variabel $n



dalam notasi heksadesimal ( X



) dengan dua digit ( 02



).



Memvisualisasikan String Biner



Meskipun dalam PHP integer selalu 32 atau 64 bit, panjang string sama dengan panjang isinya. Untuk memecahkan kode nilai biner dan merendernya, kita perlu memeriksa dan mengubah setiap byte.



Untungnya, dalam PHP, string tidak dinamai seperti array, dan setiap posisi menunjuk ke karakter 1-byte. Berikut contoh mengakses simbol:



<?php
$str = 'thephp.website';

echo $str[3];
echo $str[4];
echo $str[5];

// Outputs:
php

      
      





Dengan asumsi satu karakter adalah 1 byte, kita dapat memanggil ord () untuk mentransmisikan ke integer 1-byte:



<?php
$str = 'thephp.website';

$f = ord($str[3]);
$s = ord($str[4]);
$t = ord($str[5]);

echo sprintf(
  '%02X %02X %02X',
  $f,
  $s,
  $t,
);
// Outputs:
70 68 70

      
      





Sekarang Anda dapat memeriksa ulang dengan aplikasi baris perintah hexdump:



$ echo 'php' | hexdump
// Outputs
0000000 70 68 70 ...

      
      





Kolom pertama hanya berisi alamat, dan di kolom kedua kita melihat nilai heksadesimal mewakili karakter p



, h



dan p



.



Juga saat menangani string biner, kita dapat menggunakan fungsi pack () dan unpack () , dan saya punya contoh yang bagus untuk Anda! Katakanlah Anda perlu membaca file JPEG untuk mengekstrak beberapa data (seperti EXIF). Dengan menggunakan mode baca biner, Anda dapat membuka penangan file dan langsung membaca dua byte pertama:



<?php

$h = fopen('file.jpeg', 'rb');

// Read 2 bytes
$soi = fread($h, 2);

      
      





Untuk mengekstrak nilai ke dalam array integer, Anda cukup mengekstraknya:



$ints = unpack('C*', $soi);

var_dump($ints);
// Outputs
array(2) {
  [1] => int(-1)
  [2] => int(-40)
}

echo sprintf('%02X', $ints[1]);
echo sprintf('%02X', $ints[2]);
// Outputs
FFD8

      
      





Perhatikan bahwa format C dalam fungsi tersebut unpack()



mengubah karakter menjadi string $soi



sebagai angka 8-bit yang tidak bertanda. Pengubah *



membongkar seluruh baris.



Operasi bitwise



PHP mengimplementasikan semua operasi bitwise yang mungkin Anda butuhkan. Mereka dibangun sebagai ekspresi, dan hasil pekerjaan mereka dijelaskan di bawah ini:



Kode php Nama Deskripsi
$ x | $ y Inklusif ATAU $ x dan $ y diberi nilai dengan semua bit yang diberikan.
$ x ^ $ y Eksklusif ATAU $ x atau $ y diberi nilai dengan bit yang diberikan.
$ x & $ y DAN $ x dan $ y secara bersamaan diberi nilai dengan bit yang diberikan.
~ $ x TIDAK Mengubah nilai semua bit dalam $ x.
$ x << $ y SHIFT Kiri Menggeser bit $ x yang ditinggalkan oleh posisi $ y.
$ x >> $ y SHIFT Kanan Menggeser bit $ x ke kanan dengan posisi $ y.


Saya akan menjelaskan cara kerjanya masing-masing!



Biarkan $x = 0x20



dan $y = 0x30



. Di bawah ini saya akan menunjukkan contoh menggunakan notasi biner.



Bagaimana Inklusif Atau ($ x | $ y) bekerja



Operasi OR inklusif mengambil semua bit dari kedua input. Artinya, itu $x | $y



harus kembali 0x30



. Lihatlah:



// 1 | 1 = 1
// 1 | 0 = 1
// 0 | 0 = 0

0b00100000 // $x = 0x20
0b00110000 // $y = 0x30
OR ------- // $x | $y
0b00110000 // 0x30

      
      





Catatan: Dari kanan ke kiri, bit keenam $x



(1) telah ditentukan , begitu juga bit kelima dan keenam $y



. Data dikumpulkan dan nilai yang dihasilkan mengingat kelima dan keenam bit: 0x30



.



Cara kerja Eksklusif Atau ($ x ^ $ y)



Operasi OR eksklusif (juga dikenal sebagai XOR) mengambil bit hanya dari satu sisi. Artinya, hasil perhitungannya $x ^ $y



adalah 0x10



:



// 1 ^ 1 = 0
// 1 ^ 0 = 1
// 0 ^ 0 = 0

0b00100000 // $x = 0x20
0b00110000 // $y = 0x30
XOR ------ // $x ^ $y
0b00010000 // 0x10

      
      





Bagaimana DAN ($ x & $ y) bekerja



Operator AND jauh lebih mudah untuk dipahami. Ini menerapkan operasi AND untuk setiap bit, jadi hanya nilai yang sama satu sama lain di kedua sisi yang akan diambil. Hasil perhitungannya $x & $y



adalah 0x20



:



// 1 & 1 = 1
// 1 & 0 = 0
// 0 & 0 = 0

0b00100000 // $x = 0x20
0b00110000 // $y = 0x30
AND ------ // $x & $y
0b00100000 // 0x20

      
      





Bagaimana TIDAK (~ $ x) bekerja



Operasi NOT memerlukan satu parameter, ini hanya mengubah nilai dari semua bit yang ditransmisikan. Itu mengubah semua 0 menjadi 1, dan semua 1 menjadi 0.:



// ~1 = 0
// ~0 = 1

0b00100000 // $x = 0x20
NOT ------ // ~$x
0b11011111 // 0xDF

      
      





Jika Anda melakukan operasi ini dalam PHP dan memutuskan untuk men-debug sprintf()



, Anda mungkin memperhatikan angka yang lebih luas? Dalam bab tentang Normalisasi Angka, saya akan menjelaskan apa yang terjadi di sini dan cara memperbaikinya.



Cara kerja SHIFT Kiri dan SHIFT Kanan ($ x << $ n dan $ x >> $ n)



Pergeseran bit mirip dengan mengalikan atau membagi angka dengan pangkat dua. Semua bit pergi ke $n



posisi kiri atau kanan.



Mari kita ambil bilangan biner kecil agar lebih mudah ditampilkan, misalnya $x = 0b0010



. Jika kita bergeser ke $x



kiri sekali , bit itu harus berpindah satu posisi ke kiri:



$x = 0b0010;
$x = $x << 1;
// 0b0100

      
      





Hal yang sama dengan offset ke kanan:



$x = 0b0100;
$x = $x >> 2;
// 0b0001

      
      





Artinya, menggeser jumlah $n



kali ke kiri sama dengan mengalikan $n



dua kali, dan menggeser jumlah $n



kali ke kanan sama dengan membagi dua $n



.



Apa itu bit mask



Banyak hal menarik dapat dilakukan dengan operasi ini dan teknik lainnya. Misalnya, oleskan sedikit mask. Ini adalah bilangan biner pilihan Anda, dibuat untuk mengekstrak informasi yang sangat spesifik.



Misalnya, ambil gagasan bahwa angka bertanda 8-bit positif jika bit kedelapan (0) tidak ditentukan, dan negatif jika bit ditentukan. Apakah angkanya positif atau negatif 0x20



? Tentang apa 0x81



?



Untuk menjawab ini, kita dapat membuat byte yang sangat nyaman dengan satu bit negatif yang ditentukan ( 0b10000000



, setara 0x80



) dan 0x20



DAN itu. Jika hasilnya 0x80



( 0b10000000



, topeng kami), maka ini adalah angka negatif, jika tidak, itu positif:



// 0x80 === 0b10000000 (bitmask)
// 0x20 === 0b00100000
// 0x81 === 0b10000001

0x20 & 0x80 === 0x80 // false
0x81 & 0x80 === 0x80 // true

      
      





Ini sering dibutuhkan saat bekerja dengan flag. Anda bahkan dapat menemukan contoh penggunaan di PHP itu sendiri, seperti tanda pesan kesalahan .



Anda dapat memilih jenis kesalahan yang akan dihasilkan:



error_reporting(E_WARNING | E_NOTICE);

      
      





Apa yang terjadi di sini? Lihat saja maksud Anda:



0b00000010 (0x02) E_WARNING
0b00001000 (0x08) E_NOTICE
OR -------
0b00001010 (0x0A)

      
      





Ketika PHP melihat notifikasi yang dapat dikirim, PHP akan memeriksa sesuatu seperti ini:



// error reporting we set before
$e_level = 0x0A;

// Needs to throw a notice
if ($e_level & E_NOTICE === E_NOTICE)
 // Flag is set: throws notice

      
      





Dan Anda akan melihatnya di mana-mana! Biner, prosesor, segala macam hal tingkat rendah!



Menormalkan angka



PHP memiliki satu kekhasan terkait dengan penanganan bilangan biner: bilangan bulat berukuran 32 atau 64 bit. Ini berarti bahwa kami sering kali perlu menormalkannya untuk mempercayai perhitungan kami.



Misalnya, menjalankan operasi ini pada mesin 64-bit akan memberikan hasil yang aneh (tetapi diharapkan):



echo sprintf(
  '0b%08b',
  ~0x20
);

// Expected
0b11011111
// Actual
0b1111111111111111111111111111111111111111111111111111111111011111

      
      





Apa yang terjadi disini? Operasi NOT pada integer 8-bit ( 0x20



) mengubah semua bit nol menjadi satu. Tebak apa yang kita punya nol? Benar, 56 bit lainnya di kiri, yang sebelumnya diabaikan!



Sekali lagi, alasannya adalah bahwa dalam PHP panjang bilangan bulat adalah 32 atau 64 bit, berapa pun nilainya!



Namun, kodenya berfungsi seperti yang diharapkan. Misalnya, hasil operasi ~ 0x20 & 0b11011111 === 0b11011111



akan menjadi nilai boolean (true). Tetapi jangan lupa bahwa bit di sebelah kiri ini tidak pergi ke mana pun, jika tidak, Anda akan mendapatkan perilaku kode yang aneh.



Untuk mengatasi masalah ini, Anda dapat menormalkan angka dengan menerapkan bit mask yang menghapus semua nol. Misalnya untuk menormalkan ~0x20



sebuah integer 8-bit harus di-AND dengan 0xFF



( 0b11111111



) sehingga 56 bit sebelumnya menjadi nol.



~0x20 & 0xFF
-> 0b11011111

      
      





Perhatian! Jangan lupa tentang apa yang ada di variabel Anda, jika tidak, Anda akan mendapatkan perilaku yang tidak terduga. Sebagai contoh, mari kita lihat apa yang terjadi ketika kita menggeser nilai di atas ke kanan tanpa mask 8-bit:



~0x20 & 0xFF
-> 0b11011111

0b11011111 >> 2
-> 0b00110111 // expected

(~0x20 & 0xFF) >> 2
-> 0b00110111 // expected

(~0x20 >> 2) & 0xFF
-> 0b11110111 // expected?

      
      





Izinkan saya menjelaskan: dari sudut pandang PHP, ini diharapkan, karena Anda secara eksplisit memproses angka 64-bit. Anda perlu memahami apa yang diharapkan oleh program ANDA.



Tip: Hindari kesalahan konyol ini dengan memprogram dalam paradigma TDD .



Kesimpulan: Biner dan PHP itu keren



Setelah dipersenjatai dengan alat seperti itu, yang lainnya menjadi hanya menemukan dokumentasi yang benar tentang perilaku binari atau protokol. Bagaimanapun, semuanya adalah urutan biner.



Saya sangat merekomendasikan membaca spesifikasi PDF atau EXIF. Anda bahkan mungkin ingin bereksperimen dengan implementasi Anda sendiri dari format serialisasi MessagePack , atau Avro, Protobuf ... Kemungkinannya tidak terbatas!



All Articles