W C11 dodano nowy ciąg literału o przedrostku u8. Zwraca tablicę znaków z tekstem zakodowanym do UTF-8. Jak to w ogóle jest możliwe? Czy nie jest podpisany normalny char? Czy oznacza to, że ma nieco mniej informacji do użycia z powodu znaku bitowego? Moja logika przedstawiałaby, że ciąg tekstu UTF-8 musiałby być tablicą niepodpisanych znaków.W jaki sposób char [] może reprezentować ciąg znaków UTF-8?
Odpowiedz
nie jest normalną char podpisane?
Jest to zależne od tego, czy realizacja char
jest signed
lub unsigned
.
Ponadto bit znaku nie jest "zagubiony", ale może być nadal używany do reprezentowania informacji, a char
niekoniecznie ma rozmiar 8 bitów (może być większy na niektórych platformach).
* "może być również bez znaku" * ... ale nie w tym samym czasie :-) –
Standard mówi, że 'char' ma zawsze długość 1 bajta. Rozmiar bajtu może się jednak różnić. Użyj 'CHAR_BIT' (z' limits.h'), aby poznać faktyczny rozmiar 1 bajta. – jweyrich
No, trochę znak jest nieco mimo wszystko! A sama specyfikacja UTF-8 nie mówi, że znaki muszą być niepodpisane.
PS Wat voor kookwekker „n Naam?
Istnieje potencjalny problem tutaj:
Jeśli implementacja z CHAR_BIT == 8
wykorzystuje logowania wielkości reprezentację char
(tak char
jest podpisany), a następnie, gdy UTF-8 wymaga Bit-wzór 10000000
, że to negatywne 0. Więc jeśli realizacja dalej nie obsługuje negatywny 0, wówczas dany ciąg znaków UTF-8 może zawierać nieprawidłową wartość (trap) z char
, co jest problematyczne. Nawet jeśli to nie obsługuje negatywny zera, fakt, że nieco wzór 10000000
porównuje równa jako char
do bitów 00000000
(the nul terminator) mogą spowodować problemy przy użyciu UTF-8 danych w char[]
.
Myślę, że oznacza to, że w przypadku implementacji C11 o wielkości znaku, char
musi być niepodpisane. Zwykle jest to do wykonania, czy char
jest podpisany lub niepodpisane, ale oczywiście jeśli char
podpisaniu wyników w nie wdraża UTF-8 literały prawidłowo wówczas realizator musi tylko wybrać niepodpisany. Na marginesie, tak było w przypadku implementacji uzupełnień C++ w wersjach innych niż 2, ponieważ C++ pozwala na użycie char
, a także unsigned char
do uzyskiwania dostępu do reprezentacji obiektów. C tylko zezwala na unsigned char
.
w 2 za uzupełnienie i dopełnienie 1S', wzorce bitowe wymagane dla UTF-8 dane są prawidłowe wartości signed char
, więc realizacja jest wolny, aby char
albo znakiem lub bez znaku i nadal być w stanie reprezentować UTF-8 ciągi w char[]
. To dlatego, że wszystkie 256-bitowe wzorce są poprawnymi wartościami dopełniacza 2, a UTF-8 nie korzysta z bajtu 11111111
(1s 'uzupełnienie ujemnego zera).
Twój post używa niewłaściwego założenia, a mianowicie, że implementacje byłyby wystarczająco głupie, aby umożliwić podanie wartości -0 dla znaków. Nigdy nie są. –
@Mr Lister: Nie sądzę, że moja odpowiedź ma jakiekolwiek przypuszczenie co do tego, jakie implementacje faktycznie mają miejsce. Wylicza jedynie to, czego (nie) wolno robić, a zwłaszcza jedną reprezentację, która została niedawno wyklu czona przez wymóg w C11 do obsługi UTF-8. Ze względów praktycznych każda implementacja jest uzupełnieniem 2, ale standard nadal dopuszcza (głupie) alternatywy. –
Myślę, że twój wpis jest bardzo wnikliwy, ale tutaj jest miejsce, w którym jestem zdezorientowany: Standard C++ 11 zezwala na użycie 'unsigned char' i' char' do aliasingu (patrz §3.10/15), a C11 nawet pozwala na * wszystko * typy znaków (patrz §6.5/7). Dla mnie oznacza to, że typy te muszą być w stanie odczytać bajt o wartości "11111111" (lub * dowolną * inną wartość bajtu). W języku C++ 11 można to rozwiązać, tworząc zwykły znak 'char' unsigned *, jeśli * 2's nie jest używane. Ale w C11 nie można tego nigdy rozstrzygnąć, jeśli uzupełnienie 2 * nie jest * używane, ponieważ aliasing musi działać z wszystkimi typami znaków (§6.5/7), to znaczy nawet jawnie ... – JohnCand
Podpisanie znaku nie ma znaczenia; utf8 może być obsługiwane tylko z operacjami shift i maskowania (które mogą być uciążliwe dla typów podpisanych, ale nie niemożliwe) Ale: utf8 potrzebuje co najmniej 8 bitów, więc "assert (CHAR_BIT> = 8);"
Aby zilustrować według punktu: poniższe fragmenty nie zawierają żadnych operacji arytmetycznych na wartości znaku, tylko przesunięcie maski &.
static int eat_utf8(unsigned char *str, unsigned len, unsigned *target)
{
unsigned val = 0;
unsigned todo;
if (!len) return 0;
val = str[0];
if ((val & 0x80) == 0x00) { if (target) *target = val; return 1; }
else if ((val & 0xe0) == 0xc0) { val &= 0x1f; todo = 1; }
else if ((val & 0xf0) == 0xe0) { val &= 0x0f; todo = 2; }
else if ((val & 0xf8) == 0xf0) { val &= 0x07; todo = 3; }
else if ((val & 0xfc) == 0xf8) { val &= 0x03; todo = 4; }
else if ((val & 0xfe) == 0xfc) { val &= 0x01; todo = 5; }
else { /* Default (Not in the spec) */
if (target) *target = val;
return -1; }
len--;str++;
if (todo > len) { return -todo; }
for(len=todo;todo--;) {
/* For validity checking we should also
** test if ((*str & 0xc0) == 0x80) here */
val <<= 6;
val |= *str++ & 0x3f;
}
if (target) *target = val;
return 1+ len;
}
Należy pamiętać, że Standard _guarantees_ 'CHAR_BIT' ≥ 8. –
- 1. Utwórz nieprawidłowy ciąg znaków UTF8?
- 2. Przykład nieprawidłowy ciąg znaków utf8?
- 3. Powtórz ciąg znaków char według char
- 4. Jak przekonwertować ciąg znaków na UTF8 w Ruby
- 5. W Go, w jaki sposób uzyskać ciąg znaków reprezentujący strukturę?
- 6. Konwertuj ciąg znaków UTF8 na ASCII w Perlu
- 7. WPF: w jaki sposób FlowDirection.RightToLeft zmienić ciąg znaków?
- 8. java kodowanie utf8 - char, typy łańcuchowe
- 9. PHP preg_split utf8 znaków
- 10. Pozbądź się znaków alfanumerycznych z arabskiego UTF8 + ciąg angielski
- 11. W jaki sposób można reprezentować zaplanowane zdarzenia w RDBMS?
- 12. MySQL - Konwersja znaków latin1 na stole UTF8 w UTF8
- 13. ciąg podzielonego przez char
- 14. Jaki jest właściwy sposób obsługi ciągów char *?
- 15. .NET/C# - Konwertuj char [] na ciąg
- 16. Jak przekonwertować ciąg znaków UTF8 na tablicę bajtów?
- 17. MySQL Nieprawidłowy UTF8 ciąg znaków podczas importowania tabeli csv
- 18. Remove „\” char ciąg od C#
- 19. UTF8 bajt [] do konwersji ciągów znaków
- 20. Poprawny sposób zwraca ciąg znaków z funkcji
- 21. gałązka przekonwertować ciąg do obiektu, który reprezentować
- 22. Jak reprezentować kod Unicode Chr w literale VB.Net String?
- 23. Czy istnieją znaki ograniczające dla znaków UTF8?
- 24. Konwersja char [] tablice na ciąg
- 25. Jak przekonwertować "u00e9" na utf8 char, w mysql lub php?
- 26. Wykrywanie utf8 zepsutych znaków w MySQL
- 27. W języku C#, jaki jest najlepszy sposób, aby przeanalizować tę wartość z ciąg znaków?
- 28. Konwertuj ciąg łaciński1 na utf8?
- 29. Konwertuj wektor <char> na ciąg znaków z konwersją
- 30. Regex do usuwania znaków niealfanumerycznych ze znaków UTF8
UTF-8 reprezentuje znaki używające więcej niż 8 bitów (co zawsze mnie myli, ponieważ UTF-16 ma 16 bitów). Ponadto, znak jest tylko grupą bitów, więc być może jest podpisany lub nie ma znaczenia, jeśli myślisz o wartości jako liczbie. Jeśli myślisz o tym, że jest (częścią) reprezentacji symbolu utf-8, to czy kompilator myśli, że obszar w pamięci reprezentuje liczbę podpisaną lub niepodpisaną, nie ma znaczenia. (To nie jest odpowiedź, tylko jak moja logika to interpretuje.) – Oliver
@Oliver Co jest częścią, która Cię myli? UTFf-8 jest tak samo 8-bitowy, jak UTF-16 ma 16 bitów. –
Znaki @MrLister UTF-16 zajmują 1 lub 2 bajty pamięci. Znaki UTF-8 mogą zajmować dowolną liczbę pamięci (zwykle od 1 do 6 bajtów). Moim zdaniem, "UTF-8" byłby 8-bitowym kodowaniem podobnym do ASCII. Prawdziwy UTF-8 byłby lepszy pod nazwą UTF-48 lub podobnym. A przynajmniej myślę, że tak to działa. Nigdy naprawdę nie rozumiałem kodowania znaków o zmiennej szerokości, kiedy robiłem C kilka lat temu, a teraz pracuję w szczęśliwszych językach, gdzie to naprawdę nie jest problemem ... – Oliver