Как кодирование файлов влияет на строковые литералы C++11?
Вы можете написать строковые литералы UTF-8/16/32 в C++11, добавив к строковому литералу префикс u8/u/U соответственно. Как компилятор должен интерпретировать файл UTF-8, содержащий символы, отличные от ASCII, внутри этих новых типов строковых литералов? Я понимаю, что стандарт не определяет кодировки файлов, и один этот факт сделает интерпретацию символов, не являющихся ASCII, в исходном коде полностью неопределенным поведением, что делает эту функцию чуть менее полезной.
I поймите, вы все еще можете экранировать отдельные символы юникода с помощью uNNNN, но это не очень читаемо, скажем, для полного русского или французского предложения, которое обычно содержит более одного символа Юникода.
Из различных источников я понимаю, что
u должен стать эквивалентным L в текущих реализациях Windows и U, например, в реализациях Linux. Поэтому, имея это в виду, мне также интересно, каково требуемое поведение для старого строкового литерала модификаторы...Для обезьян-образцов кода:
string utf8string a = u8"L'hôtel de ville doit être là-bas. Ça c'est un fait!";
string utf16string b = u"L'hôtel de ville doit être là-bas. Ça c'est un fait!";
string utf32string c = U"L'hôtel de ville doit être là-bas. Ça c'est un fait!";
В идеальном мире все эти строки производят одинаковое содержание (как в: символы после преобразования), но мой опыт работы с C++ научил меня, что это наиболее определенно определенная реализация и, вероятно, только первая будет делать то, что я хочу.
3 ответов:
В GCC используйте
-finput-charset=charset:Задайте входной набор символов, используемый для перевода из набора символов входного файла в исходный набор символов, используемый GCC. Если языковой стандарт не указан или GCC не может получить эту информацию из языкового стандарта, по умолчанию используется UTF-8. Этот параметр можно переопределить либо с помощью локали, либо с помощью этого параметра командной строки. В настоящее время параметр командной строки имеет приоритет, если есть конфликт. кодировка может быть любой кодировкой, поддерживаемой системой " iconv" обычной библиотеке.
Также проверьте параметры
-fexec-charsetи-fwide-exec-charset.Наконец, о строковых литералах:
char a[] = "Hello"; wchar_t b[] = L"Hello"; char16_t c[] = u"Hello"; char32_t d[] = U"Hello";Модификатор размера строкового литерала (
L,u,U) просто определяет тип литерала.
Как компилятор должен интерпретировать файл UTF-8, содержащий символы, отличные от ASCII, внутри этих новых типов строковых литералов. Я понимаю, что стандарт не определяет кодировки файлов, и один этот факт сделает интерпретацию символов, не являющихся ASCII, в исходном коде полностью неопределенным поведением, что делает эту функцию чуть менее полезной.
Из n3290, 2.2 фазы перевода [lex.фазы]
Существует множество стандартных терминов, используемых для описания того, как реализация работает с кодировками. Вот моя попытка несколько более простого, пошагового описания того, что происходит:Физические символы исходного файла отображаются, в один реализация-определенный способ, к базовому исходному набору символов (ввод символов новой строки для индикаторов конца строки), если необходимый. Набор символов физического исходного файла принимается следующим образом реализация-определена. [Вот немного о триграфах.] Любой источник заменяется символ файла, отсутствующий в базовом исходном наборе символов (2.3). именем универсального символа, которое обозначает этот символ. (- реализация может использовать любую внутреннюю кодировку, если фактическая расширенный символ, встречающийся в исходном файле, и то же самое расширенный символ, выраженный в исходном файле в виде универсальное-символьное-имя (то есть, используя обозначение \uXXXX), являются обрабатывается эквивалентно, за исключением случаев, когда эта замена возвращается в необработанный строковый литерал.)
Физические символы исходного файла отображаются в виде реализация-определенный способ, к базовому исходному набору символов [...]
Проблема кодировок файлов решается вручную; стандарт заботится только о базовом исходном наборе символов и оставляет место для реализации, чтобы добраться туда.
Любой источник заменяется символ файла, отсутствующий в базовом исходном наборе символов (2.3). именем универсального символа, которое обозначает этот символ.
Основные исходный набор-это простой список разрешенных символов. это не ASCII (см. Далее). Все, что не входит в этот список, "трансформируется" (по крайней мере, концептуально) в форму
Таким образом, независимо от того, какой тип буквальной или файловой кодировки используется, исходный код концептуально преобразуется в базовый набор символов + набор\uXXXX.\uXXXX. Я говорю концептуально, потому что то, что на самом деле делают реализации, обычно проще, например, потому что они могут иметь дело с Unicode напрямую. Важная часть-это то, что стандарт называет расширенным символом (т. е. не из базового исходного набора), должно быть неотличимо в использовании от его эквивалентной формы\uXXXX. Обратите внимание, что C++03 доступен, например, на платформах EBCDIC, поэтому ваши рассуждения в терминах ASCII ошибочны с самого начала. Наконец, процесс, который я описал, происходит и с (не сырыми) строковыми литералами. Это означает, что ваш код эквивалентен, как если бы вы написали:string utf8string a = u8"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!"; string utf16string b = u"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!"; string utf32string c = U"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!";
В принципе, вопросы кодирования имеют значение только тогда, когда вы выводите свои строки, делая их видимыми для людей, что не является вопросом определения языка программирования, поскольку его определение имеет дело только с вычислениями кодирования. Поэтому, когда вы решите, будет ли то, что вы видите в своем редакторе, таким же, как и то, что вы видите в выходных данных (любые изображения, будь то на экране или в pdf), вы должны спросить себя, каким образом ваша библиотека взаимодействия с пользователем и ваша библиотека взаимодействия с другими пользователями будут совпадать. операционная система была закодирована заранее. (Вот, например, такая информация для Qt5 : с Qt5 то, что вы видите как пользователь приложения и то, что вы видите как его программист, совпадает, если содержимое старомодных строковых литералов для ваших QStrings кодируется как utf8 в ваших исходных файлах, если вы не включаете другую настройку в процессе выполнения приложения).
В качестве вывода я думаю, что Керрек СБ прав, а Деймон ошибается: действительно, методы указание литерала в коде должно указывать его тип, а не кодировку, которая используется в исходном файле для заполнения его содержимого, поскольку тип литерала-это то, что касается вычислений, выполняемых с ним. Что-то вроде
u"string"- это просто массив "unicode codeunits" (то есть значений типаchar16_t), независимо от того, что операционная система или любое другое сервисное программное обеспечение позже делает с ними, и независимо от того, что их работа ищет вас или другого пользователя. Вы просто переходите к проблеме добавления другого соглашения для вы сами, что делает соответствие между "смыслом" чисел при вычислении (а именно, они представляют коды Unicode), и их представлением на вашем экране, когда вы работаете в текстовом редакторе. Как и используете ли вы как программист это "значение"-другой вопрос, и как вы могли бы обеспечить это другое соответствие, естественно, будет определяться реализацией, потому что это не имеет ничего общего с вычислениями кодирования, только с удобством использования инструмента.
Comments