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

Как кодирование файлов влияет на строковые литералы С++ 11?

Вы можете написать строковые литералы UTF-8/16/32 в С++ 11, префикс строкового литерала с помощью u8/u/u соответственно. Как компилятор должен интерпретировать UTF-8 файл с не-ASCII-символами внутри этих новых типов строковых литералов? Я понимаю, что в стандарте не указаны кодировки файлов, и этот факт позволил бы полностью интерпретировать символы не-ASCII внутри исходного кода undefined, делая эту функцию чуть менее полезной.

Я понимаю, что вы все равно можете избежать одиночных символов Unicode с помощью \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!";

В идеальном мире все эти строки производят одинаковый контент (например, символы после преобразования), но мой опыт работы с С++ научил меня, что это определенно определенная реализация, и, возможно, только первая сделает то, что я хочу,

4b9b3361

Ответ 1

В GCC используйте -finput-charset=charset:

Задайте входной набор символов, используемый для перевода из набора символов входного файла в исходный набор символов, используемый GCC. Если локаль не указывает, или GCC не может получить эту информацию из локали, по умолчанию используется UTF-8. Это может быть отменено либо параметром locale, либо этой командной строкой. В настоящее время параметр командной строки имеет приоритет, если есть конфликт. charset может быть любой кодировкой, поддерживаемой системной библиотекой "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) просто определяет тип литерала.

Ответ 2

Как должен компилятор интерпретировать UTF-8 файл с не-ASCII-символами внутри этих новых типов строковых литералов. Я понимаю, что в стандарте не указаны кодировки файлов, и этот факт позволил бы полностью интерпретировать символы не-ASCII внутри исходного кода undefined, делая эту функцию чуть менее полезной.

Из n3290, 2.2 Фазы перевода [lex.phases]

Изображения физического исходного файла отображаются в определяемый реализацией, базовому набору символов источника (ввод символов новой строки для индикаторов конца строки), если необходимо. Набор принятых символов физического исходного файла реализации. [Здесь немного о триграфах.] Любой источник символ файла не в базовом наборе символов источника (2.3) заменяется с помощью универсального символьного имени, которое обозначает этот символ. (An реализация может использовать любое внутреннее кодирование, если фактическое расширенный символ, встречающийся в исходном файле, и тот же расширенный символ, выраженный в исходном файле как имя универсального символа (т.е. с использованием обозначения \uXXXX), являются за исключением случаев, когда эта замена возвращается в raw string literal.)

Существует множество стандартных терминов, используемых для описания того, как реализация связана с кодировками. Здесь моя попытка как-то более простого, пошагового описания того, что происходит:

Изображения физического исходного файла отображаются в определенный реализацией, к базовому набору символов источника [...]

Проблема кодировок файлов выполняется вручную; Стандарт заботится только об основном наборе символов и оставляет место для реализации, чтобы добраться туда.

Любой источник символ файла не в базовом наборе символов источника (2.3) заменяется по имени универсального символа, которое обозначает этот символ.

Основной набор источников - это простой список допустимых символов. Это не ASCII (см. Далее). Все, что не в этом списке, "преобразуется" (по крайней мере, концептуально) в форму \uXXXX.

Итак, независимо от того, какой тип литерала или файла используется, исходный код концептуально преобразуется в базовый набор символов + набор из \uXXXX. Я говорю концептуально, потому что то, что на самом деле реализует реализация, обычно проще, например. потому что они могут напрямую обращаться к Unicode. Важная часть состоит в том, что то, что Стандарт вызывает расширенный символ (т.е. Не из базового исходного набора), должен быть неотличимым от использования его эквивалентной формы \uXXXX. Обратите внимание, что С++ 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!";

Ответ 3

В принципе, вопросы кодирования имеют значение только тогда, когда вы выводите свои строки, делая их видимыми для людей, что не является вопросом о том, как определяется язык программирования, поскольку его определение касается только вычисления кодирования. Итак, когда вы решаете, будет ли то, что вы видите в своем редакторе, будет таким же, как то, что вы видите на выходе (любые изображения, будь то на экране или в pdf), вы должны спросить себя, какое соглашение как предполагала ваша библиотека взаимодействия с пользователем и ваша операционная система. (Вот, например, такая информация для Qt5: с Qt5, что вы видите как пользователь приложения и что вы видите как его программист совпадает, если содержимое старомодных строковых литералов для ваших QStrings кодируется как utf8 в ваших исходных файлах, если только вы не включите другой параметр в ходе выполнения приложения).

В качестве вывода я считаю, что Kerrek SB прав, а Деймон ошибается: действительно, методы указания литерала в коде должны указывать его тип, а не кодировку, которая используется в исходном файле для заполнения его содержимого, поскольку тип литерала - это то, что касается вычислений. Что-то вроде u"string" - это всего лишь массив "unicode codeunits" (то есть значения типа char16_t), независимо от того, какая операционная система или какое-либо другое служебное программное обеспечение впоследствии делает с ними, и, тем не менее, их работа ищет вас или другого пользователя, Вы просто получаете проблему добавления другого соглашения для себя, что делает соответствие между "значением" вычисляемых чисел (а именно, они представляют коды Unicode) и их представлением на вашем экране при работе в текстовом редакторе, Как и если вы, как программист, используете это "значение", это другой вопрос, и как вы могли бы применять эту другую корреспонденцию, естественно, будет определяться реализацией, поскольку она не имеет ничего общего с вычислением кодировки, только с комфортом использования инструмента.