Dart TypedData dan representasi endian besar / kecil

Dec 20 2020

Jika saya menjalankan kode berikut:

Uint8List bytes = Uint8List.fromList([1, 0, 0, 128]);
ByteBuffer byteBuffer = bytes.buffer;
Uint16List sixteenBitList = byteBuffer.asUint16List();
print(sixteenBitList);

Saya mendapatkan hasil sebagai berikut:

[1, 32768]

Sejak nilai aslinya

00000001 00000000 00000000 10000000
1        0        0        128

Saya berharap mereka digabungkan seperti ini:

0000000100000000 0000000010000000
256              128

Sebagai gantinya, saya mendapatkan ini:

0000000000000001 1000000000000000
1                32768

Itu little endian, bukan? Saya menjalankan kode ini di Mac saya. Apakah alasan saya mendapatkan hasil di atas karena Mac saya menggunakan little endian? Jika saya menjalankan kode yang sama pada komputer big endian, apakah akan memberikan hasil yang berbeda? (Saya mendapatkan hasil yang sama di DartPad, tetapi saya tidak tahu mesin apa yang menjalankan DartPad.)

Jawaban

3 ChristopherMoore Dec 20 2020 at 12:03

Ya, diharapkan bisa memberikan hasil yang berbeda. Anda akan mendapatkan hasil yang diharapkan pada sistem big endian. Metode Anda saat ini untuk melihat data byte Anda menggunakan endianness dari sistem host. Ini termasuk DartPad karena kode yang berjalan di DartPad sedang dikompilasi ke JS, yang masih berjalan di sistem endian kecil yang sama.

Tidak ada batasan pasti untuk bahasa Dart. Namun, beberapa metode melihat data byte secara eksplisit menetapkan endianness seperti ByteDatakelas.

1 Suragch Dec 28 2020 at 07:10

Berikut adalah beberapa informasi tambahan untuk jawaban Christopher Moore.

Anda dapat memeriksa ketahanan komputer Anda dengan yang berikut ini:

print(Endian.host == Endian.little);

Kebanyakan komputer pribadi menggunakan arsitektur little endian sehingga biasanya akan kembali true.

Anda dapat menentukan endian yang ingin Anda gunakan untuk melihat data dengan menggunakan ByteDataalih-alih BytesBuffer:

import 'dart:typed_data';

void main() {
  Uint8List byteList = Uint8List.fromList([1, 0, 0, 128]);
  ByteData byteData = ByteData.sublistView(byteList);

  int value = byteData.getUint16(0, Endian.big);
  print(value.toRadixString(2).padLeft(16, '0'));
  
  value = byteData.getUint16(2, Endian.big);
  print(value.toRadixString(2).padLeft(16, '0'));
}

Hasilnya adalah:

0000000100000000 0000000010000000

Jika Anda mengubah Endian.bigke Endian.littlehasilnya akan:

0000000000000001 1000000000000000

Anda dapat membaca lebih lanjut tentang ini di sini:

  • Bekerja dengan byte di Dart