Подтвердить что ты не робот

Поведение расширенных байтов/символов в локали C/POSIX

C и POSIX требуют наличия только очень ограниченного набора символов в локали C/POSIX, но допускают существование дополнительных символов. Это оставляет большую свободу для реализации; например, поддержка всех Unicode (как UTF-8) в локали C соответствует поведению. Однако большинство исторических реализаций относятся к языку C как к 8-битовому чистому однобайтовому кодированию символов: ISO-8859-1 (Latin-1) или своего рода "абстрактному 8-битовому набору символов", где байты без ASCII являются абстрактными символами без определенного идентификатора. (Однако в последнем случае, если компилятор определяет __STDC_ISO_10646__, они нормативно соответствуют символам Unicode, обычно диапазону Latin-1.)

Другим подходящим вариантом, который кажется гораздо менее популярным, является обработка всех байтов без ASCII как несимвольных, то есть ответ на них с ошибкой EILSEQ.

Мне интересно знать, существуют ли реализации, которые используют этот или любые другие необычные варианты реализации языковой версии C. Существуют ли реализации, в которых попытка конвертировать "высокие байты" в локаль C приводит к EILSEQ или к чему-то другому, кроме как обрабатывать их как (абстрактные или латинские-1) однобайтовые символы или UTF-8?

4b9b3361

Ответ 1

От комментария к предыдущему ответу:

Способы ошибочного предположения в основном состоят в том, что байты вне переносимого набора символов могут быть незаконными несимвольными байтами (EILSEQ) или составлять некоторую многобайтовую кодировку (UTF-8 или устаревшее кодирование CJK)

Здесь вы можете найти один пример.

План 9 поддерживает только локаль C. Как вы можете видеть в utf.c и rune.c, когда он находит руну за пределами переносимых символов, она просто обрабатывает ее как символ из другой кодировки.

Другими кандидатами могут быть Minix, а * Семейство BSD (поскольку они используют citrus). В исходном коде Minix я также нашел команду file, которая ищет новую кодировку, когда размер символа не равен 8 бит.

Ответ 2

"Мне интересно знать, есть ли реализации, которые берут этот или любые другие необычные варианты при реализации языкового стандарта C".

Этот вопрос очень сложно ответить, поскольку он смешивает "C Locale", который я предполагаю, относится к ограниченному набору символов C Standard, упомянутому выше, с "другими необычными вариантами", который я предполагаю, относится к тому, как конкретная реализация обрабатывает символы вне (ограниченный) язык C. Каждая реализация C должна внедрять C Locale; Я не думаю, что там есть какие-то необычные варианты.

Предположим для аргумента, что вопрос заключается в следующем: "... необычные варианты при реализации дополнительных/расширенных символов за пределами языкового стандарта C". Теперь это становится вопросом, зависящим от реализации, и, как вы уже упоминали, он "оставляет большую свободу для реализации". Поэтому, не зная целевого компилятора/аппаратного обеспечения, все равно будет сложно ответить окончательно.

Теперь последняя часть:

"... попытка конвертировать" высокие байты "в локаль C приводит к EILSEQ или к чему-то другому, кроме как рассматривать их как (абстрактные или латинские-1) однобайтные символы или UTF-8?"

Вместо преобразования больших байтов в C Locale вы можете установить Locale в своей программе, как в этом SO-вопросе: Означает ли базовый набор символов только C:

Таким образом, вы можете гарантировать, что ваши персонажи будут обработаны в Locale, который вы ожидаете.


Я понимаю, что C Locale относится только к первым 7-битным (8-разрядным типом char), основанным на следующих источниках:

Термины "высокие байты" и "Юникод" и "UTF-8" относятся к классу многобайтовых или широкосимвольных кодировок и являются специфическими для локали (и вне диапазона минимального C Locale). Я не понимаю, как можно "конвертировать большие байты" в (чистый) C Locale. Вполне возможно, что реализации выбрали бы стандартную (расширенную) локаль, если ни один из них не был явно установлен (или вытащил ее из настроек среды ОС, как указано в одной из вышеперечисленных ссылок).

Ответ 3

Поразительно, я просто обнаружил, что наиболее широко используемая реализация glibc - это пример того, что я ищу. Рассмотрим эту простую программу:

#include <stdlib.h>
#include <stdio.h>
int main()
{
        wchar_t wc = 0;
        int n = mbtowc(&wc, "\x80", 1);
        printf("%d %.4x\n", n, (int)wc);
}

В glibc он печатает -1 0000. Если байт 0x80 был расширенным символом в локали реализации C/POSIX, он будет печатать 1, за которым следует некоторый ненулевой номер символа.

Таким образом, "общее знание", что языковой стандарт C/POSIX "8-бит-чистый" в glibc, является просто ложным. Что происходит, так это то, что существует грубая несогласованность; несмотря на то, что все стандартные утилиты, согласование регулярных выражений и т.д. заданы для работы с (многобайтовыми) символами, как если бы они читались с помощью mbrtowc, реализации этих утилит/функций принимают ярлык, когда они видят MB_CUR_MAX==1 или LC_CTYPE содержащий "C" (или аналогичный) и считывающий значения char непосредственно вместо обработки ввода с помощью mbrtowc или аналогичного. Это приводит к несогласованности между указанным поведением (которое, поскольку их реализация локали C/POSIX определено, должно обрабатывать большие байты как незаконные последовательности) и поведение реализации (которое полностью обходит систему локали).

Со всем сказанным я все еще ищу другие реализации со свойствами, заданными в вопросе.