В C11 добавлен новый строковый литерал с префиксом u8. Это возвращает массив символов с текстом, закодированным в UTF-8. Как это вообще возможно? Разве обычный символ не подписан? Это означает, что у него на один бит меньше информации для использования из-за знакового бита? Моя логика изображала бы, что строка текста UTF-8 должна быть массивом беззнаковых символов.
Как char[] может представлять строку UTF-8?
Ответы (4)
Разве обычный символ не подписан?
Это зависит от реализации, является ли char
signed
или unsigned
.
Кроме того, бит знака не «теряется», его все еще можно использовать для представления информации, а char
не обязательно имеет размер 8 бит (на некоторых платформах он может быть больше).
char
всегда имеет длину 1 байт. Однако размер байта может варьироваться. Используйте CHAR_BIT
(из limits.h
), чтобы узнать фактический размер 1 байта.
- person jweyrich; 12.01.2012
Здесь есть потенциальная проблема:
Если реализация с CHAR_BIT == 8
использует представление величины знака для char
(поэтому char
является знаковым), то когда UTF-8 требует битового шаблона 10000000
, это отрицательный 0. Таким образом, if em> реализация также не поддерживает отрицательный 0, тогда заданная строка UTF-8 может содержать недопустимое (ловушку) значение 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).
unsigned char
и char
для псевдонимов (см. §3.10/15), а C11 даже позволяет все типы символов (см. §6.5/7). Для меня это означает, что эти типы должны быть способны читать байт со значением 11111111
(или любое другое значение байта). В C++11 это можно решить, создав простой char
unsigned если дополнение 2 не используется. Но в C11 это никогда не может быть решено, если дополнение 2 не используется, потому что сглаживание должно работать со всеми типами символов (§6.5/7), то есть даже явно...
- person JohnCand; 13.11.2013
Нет, бит знака все же немного! И сама спецификация UTF-8 не говорит, что символы должны быть без знака.
PS Что такое kookwekker voor 'n naam?
Подпись char не имеет значения; utf8 можно обрабатывать только с помощью операций сдвига и маски (что может быть громоздко для подписанных типов, но не невозможно).
Для иллюстрации по пунктам: следующие фрагменты не содержат арифметических операций над значением символа, только сдвиг и маска.
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;
}
CHAR_BIT
≥ 8.
- person J. C. Salomon; 31.01.2012
unsigned char
для байтовых представлений объектов. - person u0b34a0f6ae   schedule 12.01.2012