Как char [] может представлять строку UTF-8? - PullRequest
8 голосов
/ 11 января 2012

В C11 добавлен новый строковый литерал с префиксом u8.Это возвращает массив символов с текстом, закодированным в UTF-8.Как это вообще возможно?Разве нормальный символ не подписан?Это означает, что из-за знака-бита у него на один бит меньше информации?Моя логика должна изобразить, что строка текста UTF-8 должна быть массивом беззнаковых символов

Ответы [ 4 ]

6 голосов
/ 11 января 2012

Здесь есть потенциальная проблема:

Если реализация с CHAR_BIT == 8 использует представление величины знака для char (таким образом, char подписано), тогда когда UTF-8 требует битовый шаблон 10000000, который является отрицательным 0. Так что , если реализация далее не поддерживает отрицательный 0, то данная строка UTF-8 может содержать недопустимое (trap) значение char, что проблематично.Даже если он поддерживает отрицательный ноль, тот факт, что битовая комбинация 10000000 сравнивается равной char с битовой комбинацией 00000000 (нулевой терминатор), может вызвать проблемы при использовании данных UTF-8 в char[].

Я думаю, это означает, что для реализаций знака C11 значение char должно быть без знака.Обычно реализация зависит от того, является ли char подписанным или неподписанным, но, конечно, если подпись char приводит к неправильной реализации литералов UTF-8, тогда исполнителю просто нужно выбрать неподписанный.Кроме того, это имело место для реализаций C ++, не являющихся дополнениями 2, поскольку C ++ позволяет использовать char, а также unsigned char для доступа к представлениям объектов.C допускает только unsigned char.

В дополнении 2 и дополнении 1 битовые комбинации, требуемые для данных UTF-8, являются действительными значениями signed char, поэтому реализация может сделать char подписаннымили без знака и по-прежнему может представлять строки UTF-8 в char[].Это потому, что все 256-битные шаблоны являются допустимыми значениями дополнения 2, и UTF-8 не использует байт 11111111 (отрицательный ноль дополнения 1 с).

6 голосов
/ 11 января 2012

Разве нормальный символ не подписан?

Это зависит от реализации, является ли char signed или unsigned.

Далее, знакбит не «потерян», его все еще можно использовать для представления информации, и char не обязательно имеет размер 8 бит (на некоторых платформах он может быть больше).

1 голос
/ 11 января 2012

Подпись char не имеет значения; utf8 может обрабатываться только с помощью операций сдвига и маски (что может быть громоздким для подписанных типов, но не невозможно). Но: utf8 требуется не менее 8 бит, поэтому "assert (CHAR_BIT> = 8);"

Для иллюстрации по пунктам: следующие фрагменты не содержат арифметических операций над значением символа, только сдвиг и маска.

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;
}
1 голос
/ 11 января 2012

Нет, бит знака немного!И сама спецификация UTF-8 не говорит о том, что символы должны быть без знака.

PS Wat is kookwekker voor 'n naam?

...