(1) Co oznacza sekwencja bajtów, arrary char w C? Czy UTF-16 jest sekwencją bajtów lub co to jest? (2) Dlaczego sekwencja bajtów nie ma nic wspólnego ze zmienną długością?
Wygląda na to, że nie rozumiesz, jakie są problemy związane z endianem. Oto krótkie podsumowanie.
32-bitowa liczba całkowita zajmuje 4 bajty. Teraz znamy logiczną kolejność tych bajtów. Jeśli masz 32-bitową liczbę całkowitą, możesz uzyskać jej wyższy bajt za pomocą następującego kodu:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
Wszystko dobrze i dobrze. Problem zaczyna się od tego, jak różne urządzenia zapisują i pobierają liczby całkowite z pamięci.
W kolejności Big Endian 4 bajtowa pamięć, którą odczytujesz jako 32-bitową liczbę całkowitą, zostanie odczytana, a pierwszy bajt będzie bajtem najwyższym:
[0][1][2][3]
W kolejności Little Endian 4-bajtowa pamięć, którą odczytujesz jako 32-bitową liczbę całkowitą, zostanie odczytana, przy czym pierwszy bajt będzie bajtem niższym :
[3][2][1][0]
Jeśli masz wskaźnik do wskaźnika do wartości 32-bitowej, możesz to zrobić:
uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?
Według C / C ++ wynik tego jest niezdefiniowany. Może to być 0x81. Lub może to być 0x32. Technicznie rzecz biorąc, może zwrócić wszystko, ale w przypadku prawdziwych systemów zwróci jedno lub drugie.
Jeśli masz wskaźnik do adresu pamięci, możesz odczytać ten adres jako wartość 32-bitową, 16-bitową lub 8-bitową. Na dużej maszynie Endian wskaźnik wskazuje na wysoki bajt; na małej maszynie Endian wskaźnik wskazuje na niski bajt.
Zauważ, że chodzi o czytanie i pisanie do / z pamięci. Nie ma to nic wspólnego z wewnętrznym kodem C / C ++. Pierwsza wersja kodu, ta, której C / C ++ nie deklaruje jako niezdefiniowany, zawsze będzie działać, aby uzyskać wysoki bajt.
Problem polega na tym, gdy zaczynasz czytać strumienie bajtów. Tak jak z pliku.
Wartości 16-bitowe mają te same problemy, co wartości 32-bitowe; mają po prostu 2 bajty zamiast 4. Dlatego plik może zawierać 16-bitowe wartości przechowywane w dużej lub małej kolejności.
UTF-16 jest zdefiniowany jako sekwencja 16-bitowych wartości . Skutecznie jest to uint16_t[]
. Każda pojedyncza jednostka kodu ma wartość 16-bitową. Dlatego, aby poprawnie załadować UTF-16, musisz wiedzieć, co to jest endianność danych.
UTF-8 jest zdefiniowany jako ciąg wartości 8-bitowych . To jest uint8_t[]
. Każda pojedyncza jednostka kodu ma 8 bitów: jeden bajt.
Teraz zarówno UTF-16, jak i UTF-8 pozwalają na połączenie wielu jednostek kodu (wartości 16-bitowe lub 8-bitowe) w celu utworzenia punktu kodowego Unicode („znak”, ale to nie jest poprawny termin; jest to uproszczenie ). Kolejność tych jednostek kodu, które tworzą kodowy jest podyktowane UTF-16 i UTF-8 kodowania.
Podczas przetwarzania UTF-16 odczytujesz 16-bitową wartość, robiąc wszystko, czego potrzeba konwersja endian. Następnie wykrywasz, czy jest to para zastępcza; jeśli tak, to odczytujesz kolejną 16-bitową wartość, łączysz obie, a następnie otrzymujesz wartość punktu kodowego Unicode.
Podczas przetwarzania UTF-8 odczytujesz wartość 8-bitową. Żadna konwersja endiana nie jest możliwa, ponieważ jest tylko jeden bajt. Jeśli pierwszy bajt oznacza sekwencję wielobajtową, to odczytujesz pewną liczbę bajtów, zgodnie z sekwencją wielobajtową. Każdy pojedynczy bajt jest bajtem i dlatego nie ma konwersji typu endian. Kolejność tych bitów w sekwencji, tak jak kolejność pary zastępczych UTF-16 jest określona przez UTF-8.
Tak więc nie może być żadnych problemów endian z UTF-8.