Я хотел бы получить подтверждение относительно моего понимания необработанных строковых литералов и (не широкого) execution character set
на винде.
Соответствующие пункты, для которых я желаю конкретного подтверждения, выделены жирным шрифтом. Но сначала немного предыстории.
ФОН
(соответствующие вопросы в пунктах ниже в смелый)
В результате полезного обсуждения ниже @ TheUndeadFish ответ в этот вопрос, который я отправил вчера, Я пытался понять правила, определяющие набор символов а также кодирование используется в качестве execution character set
в MSVC на Windows (в смысле спецификации C ++ execution character set
; увидеть @ DietmarKühl сообщение).
Я подозреваю, что некоторые могут посчитать пустой тратой времени даже пытаться понять поведение ANSI, связанное с char *
(то есть не широкие) строки для не-ASCII символов в MSVC.
Например, рассмотрим @ IInspectable комментарий здесь:
Вы не можете выбросить строку в кодировке UTF-8 в версии ANSI
Windows API и надежда на что-нибудь вменяемое.
Обратите внимание, что в моем текущем проекте i18n для приложения на базе Windows MFC я буду удаление все вызовы не широких (то есть, ANSI) версий вызовов API, и я ожидаю, что компилятор сгенерирует execution wide-character set
строки, НЕ execution character set
(не широкие) строки внутри.
Тем не менее, я хочу Понимаю существующий код, который уже имеет некоторую интернационализацию, которая использует функции API ANSI. Даже если некоторые считают, что поведение ANSI API в строках, отличных от ASCII, является безумным, я хочу это понять.
Я думаю, как и другие, мне было трудно найти разъясненную документацию о неширокой execution character set
на винде.
В частности, потому что (не широкий) execution character set
определяется стандартом C ++ как последовательность char
(в отличие от wchar_t
), UTF-16 нельзя использовать для хранения символов в нешироко execution character set
, В наши дни имеет смысл использовать кодировку Unicode, закодированную через UTF-8 ( char
на основе кодирования), поэтому будет использоваться в качестве набора символов и кодирования execution character set
, Насколько я понимаю, это относится к Linux. Однако, к сожалению, это не дело на винде — даже MSVC 2013.
Это приводит к первому из двух моих вопросов.
Вопрос 1Пожалуйста, подтвердите, что я прав в следующем абзаце.
На этом фоне вот мой вопрос. В MSVC, включая VS 2013, кажется, что execution character set
является одним из (многих возможных) наборов символов ANSI, используя один из (многих возможных) кодовые страницы соответствующий конкретному данному набору символов ANSI для определения кодировки, а не набор символов Unicode с кодировкой UTF-8. (Обратите внимание, что я спрашиваю о NIDE-WIDE execution character set
.) Это правильно?
ФОН, ПРОДОЛЖЕНИЕ (при условии, что я прав в вопросе № 1)
Если я все правильно понимаю, то приведенный выше абзац, выделенный жирным шрифтом, является, вероятно, большой частью причины «безумия» использования ANSI API в Windows.
В частности, рассмотрим «нормальный» случай, когда Unicode и UTF-8 используются в качестве execution character set
,
В этом случае не имеет значения, на какой машине код компилируется и когда, и не имеет значения, на какой машине выполняется код и когда. Фактические необработанные байты строкового литерала всегда будут внутренне представлены в наборе символов Unicode с UTF-8 в качестве кодировки, и система времени исполнения всегда будет обрабатывать такие строки семантически, как UTF-8.
Нет такой удачи в «безумном» случае (если я правильно понимаю), в котором наборы символов ANSI и кодировки кодовой страницы используются в качестве execution character set
, В этом случае (мир Windows) поведение во время выполнения может быть пострадавших на машине, на которой компилируется код, по сравнению с машиной, на которой выполняется код.
Итак, вот вопрос № 2: Еще раз, пожалуйста, подтвердите, что я прав в следующем абзаце.
Имея в виду этот постоянный фон, я подозреваю, что: В частности, с MSVC, execution character set
и его кодировка зависит не так просто для понимания от локали, выбранной компилятор на машине, на которой работает компилятор, во время компиляции. Это определит необработанные байты для литералов символов, которые «записываются» в исполняемый файл. И во время выполнения библиотека времени выполнения MSVC C может использовать разные execution character set
и кодирование в интерпретировать необработанные байты символьных литералов, которые были записаны в исполняемый файл. Я прав?
(Я могу добавить примеры в этот вопрос в какой-то момент.)
ЗАКЛЮЧИТЕЛЬНЫЕ КОММЕНТАРИИ
По сути, если я правильно понимаю, вышеприведенный параграф объясняет «безумие» использования ANSI API в Windows. Из-за возможной разницы между набором символов ANSI и кодировкой, выбранной компилятор и набор символов и кодировка ANSI, выбранные средой выполнения C, не-ASCII-символы в строковых литералах могут не отображаться должным образом в работающей программе MSVC, когда в программе используется API-интерфейс ANSI.
(Обратите внимание, что «безумие» ANSI действительно применимо только к строковым литералам, потому что в соответствии со стандартом C ++ фактический исходный код должен быть записан в подмножестве ASCII (а комментарии исходного кода отбрасываются компилятором).)
Вышеприведенное описание — лучшее понимание API ANSI в Windows в отношении строковых литералов. Я хотел бы получить подтверждение того, что мое объяснение правильно и что мое понимание верно.
Очень длинная история, и у меня проблемы с поиском единого четкого вопроса. Тем не менее, я думаю, что я могу решить ряд недоразумений, которые привели к этому.
Во-первых, «ANSI» является синонимом (узкого) набора символов выполнения. UTF-16 — это набор широких символов исполнения.
Компилятор НЕ выберет для вас. Если вы используете узкий char
Строки, они ANSI, насколько это известно компилятору (среде выполнения).
Да, определенная кодировка символов «ANSI» может иметь значение. Если вы компилируете L"ä"
буквально на вашем компьютере, и ваш исходный код находится в CP1252, то это ä
персонаж скомпилирован в UTF-16 ä
, Однако этот же байт может быть другим не-ASCII-символом в других кодировках, что приведет к другому символу UTF-16.
Обратите внимание, что MSVC является идеально подходит для компиляции исходного кода UTF-8 и UTF-16, если он начинается с U+FEFF
«BOM». Это делает всю теоретическую проблему в значительной степени не проблема.
Нет, MSVC на самом деле не имеет ничего общего с набором символов выполнения. Значение char(0xE4)
определяется ОС. Чтобы увидеть это, проверьте компилятор MinGW. Исполняемые файлы, производимые MinGW, ведут себя так же, как исполняемые файлы MSVC, поскольку обе они предназначены для одной и той же ОС.