Использование Unicode в исходном коде C++

Какая стандартная кодировка исходного кода C++? Говорит ли что-нибудь об этом в стандарте C++? Могу ли я написать исходный код C++ в Юникоде?

Например, могу ли я использовать в комментариях символы, отличные от ASCII, например китайские символы? Если да, то разрешен ли полный Юникод или только его подмножество? (например, эта 16-битная первая страница или как там она называется.)

Кроме того, могу ли я использовать Unicode для строк? Например:

Wstring str=L"Strange chars: â Țđ ě €€";
RE: "как бы это ни называлось":Из Википедии: Первый уровень, самолет 0, Базовая многоязычная плоскость (BMP) содержит символы почти всех современных языков и большое количество символов. Основная цель BMP - поддержка унификации предшествующих наборов символов, а также символов для письма. Большинство назначенных кодовых точек в BMP используются для кодирования символов Китайский, Японский и Корейский (CJK).
DavidRR 22.04.2015 17:41

У меня был интересный вариант. У меня был символ UTF-8 µ, показанный как µ в моих журналах. Я подозревал, что GNU g ++ принял исходный код iso-8859-1 и закодировал односимвольную двухбайтовую последовательность в двоичном файле. На самом деле он понял, что источник был UTF-8 на основе локали. Журнал содержит правильную двухбайтовую последовательность. Дело в том, что другая часть журнала содержала случайные байты, которые вводили в файл байтовые последовательности, не соответствующие UTF-8. Итак, редактор emacs определил, что файл, безусловно, был ISO-8859-1, и показал двухбайтовые символы как два отдельных символа. Исправление этих случайных байтов устранило проблему.

Stéphane Gourichon 03.10.2019 19:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
58
2
41 817
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Насколько мне известно, стандарт C++ ничего не говорит о кодировке файлов с исходным кодом.

Обычной кодировкой является (или раньше была) 7-битный ASCII - некоторые компиляторы (например, Borland) отказывались от символов ASCII, в которых использовался старший бит. Нет никаких технических причин, по которым символы Unicode не могут использоваться, если ваш компилятор и редактор их принимают - большинство современных инструментов на базе Linux и многие лучшие редакторы на базе Windows без проблем обрабатывают кодировку UTF-8, хотя я Не уверен, что компилятор Microsoft это сделает.

Обновлено: похоже, что компиляторы Microsoft будут принимать файлы в кодировке Unicode, но иногда также будут выдавать ошибки на 8-битном ASCII:

warning C4819: The file contains a character that cannot be represented
in the current code page (932). Save the file in Unicode format to prevent
data loss.

Это вроде как. Я не думаю, что это явно запрещает или разрешает Unicode, но это минимально допустимый набор символов: csci.csusb.edu/dick/c++std/cd2/lex.html#lex.charset

Greg Rogers 01.12.2008 22:45

Начиная с C++ Builder2007, компилятор Borland / Codegear поддерживает исходные файлы Unicode: то есть строковые литералы Unicode, комментарии Unicode. IDe немного боролась с ними, но компилятор доволен!

Roddy 01.12.2008 23:02

Упомянутая мною вещь с Borland возникла примерно двадцать лет назад (в последний раз я пытался поместить символ высокого ASCII в файл исходного кода). :-) Я не использовал компилятор Borland около десяти лет.

Head Geek 02.12.2008 00:20

Компиляторы Microsoft поддерживают Unicode только для широких символов (L "...").

sorin 09.05.2010 23:29

Для кодирования в строках, я думаю, вы должны использовать нотацию \ u, например:

std::wstring str = L"\u20AC"; // Euro character

AFAIK Это не стандартизовано, так как вы можете помещать символы любого типа в широкие строки. Вам просто нужно убедиться, что ваш компилятор настроен на исходный код Unicode, чтобы он работал правильно.

Ответ принят как подходящий

Кодирование в C++ довольно сложно. Вот мое понимание этого.

Каждая реализация должна поддерживать символы из базовый исходный набор символов. К ним относятся общие символы, перечисленные в §2.2 / 1 (§2.3 / 1 в C++ 11). Все эти символы должны уместиться в один char. Кроме того, реализации должны поддерживать способ именования других символов, используя способ, называемый universal-character-names, и выглядящий как \uffff или \Uffffffff, и может использоваться для ссылки на символы Unicode. Некоторые из них могут использоваться в идентификаторах (перечислены в Приложении E).

Все это хорошо, но отображение символов в файле на исходные символы (используемые во время компиляции) определяется реализацией. Это составляет используемую кодировку. Вот что написано буквально (версия C++ 98):

Physical source file characters are mapped, in an implementation-defined manner, to the basic source character set (introducing new-line characters for end-of-line indicators) if necessary. Trigraph sequences (2.3) are replaced by corresponding single-character internal representations. Any source file character not in the basic source character set (2.2) is replaced by the universal-character-name that des- ignates that character. (An implementation may use any internal encoding, so long as an actual extended character encountered in the source file, and the same extended character expressed in the source file as a universal-character-name (i.e. using the \uXXXX notation), are handled equivalently.)

Для gcc вы можете изменить его, используя опцию -finput-charset=charset. Кроме того, вы можете изменить символ выполнения, используемый для представления значений во время выполнения. Подходящим вариантом для этого является -fexec-charset=charset для char (по умолчанию это utf-8) и -fwide-exec-charset=charset (по умолчанию либо utf-16, либо utf-32, в зависимости от размера wchar_t).

Также стоит отметить, что широкие символы в C++ на самом деле не являются строками Unicode как таковыми. Это просто строки из более крупных символов, обычно 16, но иногда 32 бита. Это определяется реализацией, однако, IIRC, у вас может быть 8-битный wchar_t. У вас нет реальной гарантии относительно кодировки в них, поэтому, если вы пытаетесь сделать что-то вроде обработки текста, вам, вероятно, понадобится typedef для большинства подходящий целочисленный тип для вашей сущности Unicode.

C++ 1x имеет дополнительную поддержку юникода в виде строковых литералов кодировки UTF-8 (u8"text") и типов данных UTF-16 и UTF-32 (char16_t и char32_t IIRC), а также соответствующих строковых констант (u"text" и U"text"). Кодирование символов, указанных без констант \uxxxx или \Uxxxxxxxx, по-прежнему определяется реализацией (и нет поддержки кодирования для сложных строковых типов вне литералов)

Разве строчная буква u не предназначена только для символов?

Tomasito665 21.07.2016 12:36

Здесь есть две проблемы. Во-первых, какие символы разрешены в коде C++ (и комментариях), например, имена переменных. Второй - какие символы разрешены в строках и строковых литералах.

Как уже отмечалось, компиляторы C++ должен поддерживают очень ограниченный набор символов на основе ASCII для символов, разрешенных в коде и комментариях. На практике этот набор символов не очень хорошо работал с некоторыми европейскими наборами символов (и особенно с некоторыми европейскими клавиатурами, на которых не было нескольких символов, таких как квадратные скобки), поэтому концепция орграфов и триграфов была введен. Многие компиляторы в настоящее время принимают больше, чем этот набор символов, но нет никаких гарантий.

Что касается строк и строковых литералов, в C++ есть концепция строки широких символов и строки широких символов. Однако кодировка для этого набора символов не определена. На практике это почти всегда Unicode, но я не думаю, что здесь есть какие-либо гарантии. Строковые литералы с широкими символами выглядят как L «строковый литерал», и их можно присвоить std :: wstring.


В C++ 11 добавлена ​​явная поддержка строк Unicode и строковых литералов, закодированных как UTF-8, UTF-16 с прямым порядком байтов, UTF-16 с прямым порядком байтов, UTF-32 с прямым порядком байтов и UTF-32 с прямым порядком байтов.

Помимо сообщения litb, MSVC++ также поддерживает Unicode. Я так понимаю, он получает кодировку Unicode из спецификации. Он определенно поддерживает такие коды, как int (*♫)(); или const std::set<int> ∅;. Если вам действительно нравится обфускация кода:

typedef void ‼; // Also known as \u203C
class ooɟ {
    operator ‼() {}
};

Это может быть полезно для написания, например, математического программного обеспечения, в котором исходный код может быть согласован с исходным материалом. Вы можете сделать это в Java, которая принимает исходный код UTF-8. Однако для C++ (и C) могут возникнуть проблемы с преобразованием токенов, отличных от ASCII, в имена символов, которые должны быть совместимы с остальной частью операционной системы, а не только функцией компилятора. Для C++ это можно отнести к искажению имен.

simon.watts 04.11.2014 13:55

В этом контексте, если вы получаете предупреждение MSVC++ C4819, просто измените кодировку исходного файла на «UTF-8 with Bom».

GCC 4.1 не поддерживает это, но GCC 4.4 поддерживает, а последняя версия Qt использует GCC 4.4, поэтому используйте "UTF-8 with Bom" в качестве кодировки исходного файла.

Другие вопросы по теме