(1) Chuỗi byte có nghĩa là gì, một mảng char trong C? UTF-16 là một chuỗi byte, hay nó là gì? (2) Tại sao một chuỗi byte không liên quan gì đến độ dài thay đổi?
Bạn dường như đang hiểu nhầm vấn đề endian là gì. Đây là một bản tóm tắt ngắn gọn.
Một số nguyên 32 bit chiếm 4 byte. Bây giờ, chúng ta biết thứ tự hợp lý của các byte này. Nếu bạn có số nguyên 32 bit, bạn có thể nhận được byte cao này bằng mã sau:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
Đó là tất cả tốt và tốt. Vấn đề bắt đầu là cách thức lưu trữ phần cứng và lấy số nguyên từ bộ nhớ.
Theo thứ tự Big Endian, một đoạn bộ nhớ 4 byte mà bạn đọc dưới dạng số nguyên 32 bit sẽ được đọc với byte đầu tiên là byte cao:
[0][1][2][3]
Theo thứ tự Little Endian, một đoạn bộ nhớ 4 byte mà bạn đọc dưới dạng số nguyên 32 bit sẽ được đọc với byte đầu tiên là byte thấp :
[3][2][1][0]
Nếu bạn có một con trỏ tới một con trỏ tới giá trị 32 bit, bạn có thể làm điều này:
uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?
Theo C / C ++, kết quả của điều này là không xác định. Nó có thể là 0x81. Hoặc nó có thể là 0x32. Về mặt kỹ thuật, nó có thể trả về bất cứ thứ gì, nhưng đối với các hệ thống thực, nó sẽ trả về cái này hay cái khác.
Nếu bạn có một con trỏ tới một địa chỉ bộ nhớ, bạn có thể đọc địa chỉ đó dưới dạng giá trị 32 bit, giá trị 16 bit hoặc giá trị 8 bit. Trên một máy endian lớn, con trỏ trỏ đến byte cao; trên một máy endian nhỏ, con trỏ trỏ tới byte thấp.
Lưu ý rằng đây là tất cả về đọc và ghi vào / từ bộ nhớ. Nó không có gì để làm với mã C / C ++ nội bộ. Phiên bản đầu tiên của mã, phiên bản mà C / C ++ không khai báo là không xác định, sẽ luôn hoạt động để có được byte cao.
Vấn đề là khi bạn bắt đầu đọc các luồng byte. Chẳng hạn như từ một tập tin.
Các giá trị 16 bit có cùng các vấn đề như các giá trị 32 bit; chúng chỉ có 2 byte thay vì 4. Do đó, một tệp có thể chứa các giá trị 16 bit được lưu trữ theo thứ tự endian lớn hoặc endian nhỏ.
UTF-16 được định nghĩa là một chuỗi các giá trị 16 bit . Hiệu quả, nó là một uint16_t[]
. Mỗi đơn vị mã riêng lẻ là một giá trị 16 bit. Do đó, để tải UTF-16 đúng cách, bạn phải biết tính chất cuối cùng của dữ liệu là gì.
UTF-8 được định nghĩa là một chuỗi các giá trị 8 bit . Nó là một uint8_t[]
. Mỗi đơn vị mã riêng lẻ có kích thước 8 bit: một byte đơn.
Bây giờ, cả UTF-16 và UTF-8 đều cho phép nhiều đơn vị mã (giá trị 16 bit hoặc 8 bit) kết hợp với nhau để tạo thành một bảng mã Unicode (một "ký tự", nhưng đó không phải là thuật ngữ chính xác; ). Thứ tự của các đơn vị mã này tạo thành một mật mã được quyết định bởi các bảng mã UTF-16 và UTF-8.
Khi xử lý UTF-16, bạn đọc giá trị 16 bit, thực hiện bất kỳ chuyển đổi endian nào là cần thiết. Sau đó, bạn phát hiện nếu đó là một cặp thay thế; nếu có, thì bạn đọc một giá trị 16 bit khác, kết hợp cả hai và từ đó, bạn nhận được giá trị mã điểm Unicode.
Khi xử lý UTF-8, bạn đọc giá trị 8 bit. Không thể chuyển đổi endian vì chỉ có một byte. Nếu byte đầu tiên biểu thị một chuỗi nhiều byte, thì bạn đọc một số lượng byte, như được chỉ định bởi chuỗi nhiều byte. Mỗi byte riêng lẻ là một byte và do đó không có chuyển đổi về cuối. Thứ tự của các byte này trong chuỗi, giống như thứ tự của các cặp thay thế trong UTF-16, được xác định bởi UTF-8.
Vì vậy, không thể có vấn đề về endian với UTF-8.