Предварительные условия: http://www.joelonsoftware.com/articles/Unicode.html
Приведенная выше статья является обязательной для прочтения, которая объясняет, что такое юникод, но остается мало вопросов.Да, UNICODE имеет уникальную кодовую точку для каждого символа на каждом языке, и, кроме того, они могут быть закодированы и сохранены в памяти потенциально иначе, чем фактический код.Таким образом, мы можем сэкономить память, например, используя кодировку UTF-8, что замечательно, если поддерживаемый язык - только английский, и поэтому представление памяти по существу такое же, как ASCII - это, конечно, знание самой кодировки.Теоретически, если мы знаем кодировку, мы можем хранить эти более длинные символы Юникода так, как нам нравится, и читать их обратно.Но реальный мир немного отличается.
Как сохранить символ / строку в кодировке UNICODE в программе на C ++?Какую кодировку вы используете?Ответ заключается в том, что вы не используете какую-либо кодировку, но непосредственно сохраняете кодовые точки UNICODE в строке символов Unicode, так же как вы сохраняете символы ASCII в строке ASCII.Вопрос в том, какой размер символа следует использовать, поскольку символы UNICODE не имеют фиксированного размера.Простой ответ заключается в том, что вы выбираете размер символа, который достаточно широк, чтобы в нем содержалась самая высокая кодовая точка (язык) символов, которую вы хотите поддерживать.
Теория о том, что символ UNICODE может занимать 2 байта или более, все еще верна иэто может создать некоторую путаницу.Разве мы не должны хранить кодовые точки в 3 или 4 байтах, чем то, что действительно представляет все символы Юникода?Почему Visual C ++ хранит Unicode в wchar_t, то есть всего 2 байта, явно недостаточно для хранения каждой кодовой точки UNICODE?
Причина, по которой мы храним кодовую точку UNICODE в 2 байта в Visual C ++, фактически одинаковапричина, по которой мы хранили символ ASCII (= английский) в один байт.В то время мы думали только об английском, так что одного байта было достаточно.Сейчас мы думаем о большинстве международных языков, но не обо всех, поэтому мы используем 2 байта, что достаточно.Да, это правда, что это представление не позволит нам представлять те кодовые точки, которые занимают 3 байта или более, но мы пока не заботимся о них, потому что эти люди еще даже не купили компьютер.Да, мы не используем 3 или 4 байта, потому что мы все еще скупы на память, зачем хранить лишний 0 (нулевой) байт с каждым символом, когда мы никогда не собираемся его использовать (этот язык).Опять же, это те же самые причины, по которым ASCII хранил каждый символ в одном байте, зачем хранить символ в 2 или более байтов, когда английский можно представить в одном байте, и место, которое можно выделить для этих дополнительных специальных символов!
В теории 2 байта недостаточно для представления каждой кодовой точки Unicode, но этого достаточно для хранения всего, что нас может волновать сейчас.Истинное строковое представление UNICODE может хранить каждый символ в 4 байта, но нам просто нет дела до этих языков.
Представьте себе 1000 лет спустя, когда мы найдем дружественных инопланетян в изобилии и захотим общаться с ними, используя ихбесчисленные языки.Размер единого символа Юникода увеличится, возможно, до 8 байтов, чтобы вместить все их кодовые точки.Это не значит, что мы должны начать использовать 8 байтов для каждого символа Юникода сейчас.Память является ограниченным ресурсом, мы выделяем то, что нам нужно.
Могу ли я обрабатывать строку UNICODE как строку стиля C?
В C ++ строки ASCII все еще можно обрабатывать вC ++, и это довольно часто, захватывая его указателем char *, где можно применять функции C.Однако применение текущих строковых функций в стиле C к строке UNICODE не будет иметь никакого смысла, поскольку в ней может быть один NULL-байт, заканчивающий строку C.
UNICODE string больше не является простым буфером текста, но теперь он более сложен, чем поток однобайтовых символов, заканчивающийся байтом NULL. Этот буфер может обрабатываться указателем даже в C, но для этого потребуются вызовы, совместимые с UNICODE, или библиотека C, которая могла бы читать и записывать эти строки и выполнять операции.
Это упрощается в C ++ благодаря специализированному классу, который представляет строку UNICODE. Этот класс обрабатывает сложность буфера строки Unicode и обеспечивает простой интерфейс. Этот класс также решает, является ли каждый символ строки Unicode 2 байтами или более - это детали реализации. Сегодня он может использовать wchar_t (2 байта), но завтра он может использовать 4 байта для каждого символа для поддержки более (менее известного) языка. Вот почему всегда лучше использовать TCHAR, чем фиксированный размер, который соответствует нужному размеру при изменении реализации.
Как индексировать строку UNICODE?
Стоит также отметить, особенно при обработке строк в стиле C, что они используют индекс для обхода или поиска подстроки в строке. Этот индекс в строке ASCII непосредственно соответствует позиции элемента в этой строке, но он не имеет значения в строке UNICODE и его следует избегать.
Что происходит со строкой, заканчивающейся нулевым байтом?
Строки UNICODE по-прежнему завершаются байтом NULL? Достаточно ли одного NULL-байта для завершения строки? Это вопрос реализации, но NULL-байт по-прежнему является одной кодовой точкой Юникода и, как и любая другая кодовая точка, он все равно должен иметь такой же размер, как и любой другой (особенно если кодировка отсутствует). Таким образом, символ NULL также должен составлять два байта, если реализация Unicode-строки основана на wchar_t. Все кодовые точки UNICODE будут представлены одинаковым размером независимо от того, является ли он нулевым байтом или любым другим.
Показывает ли отладчик Visual C ++ текст UNICODE?
Да, если текстовый буфер имеет тип LPWSTR или любой другой тип, поддерживающий UNICODE, Visual Studio 2005 и более поздние версии, отображающий международный текст в окне просмотра отладчика (при условии, конечно, что установлены шрифты и языковые пакеты).
Резюме:
C ++ не использует какую-либо кодировку для хранения символов Юникода, но он напрямую сохраняет кодовые точки UNICODE для каждого символа в строке. Он должен выбрать размер символа, достаточно большой, чтобы вместить самый большой символ желаемых языков (свободно говоря), и этот размер символа будет фиксированным и использоваться для всех символов в строке.
Сейчас 2 байта достаточно для представления большинства языков, которые нас интересуют, поэтому для представления кодовой точки используются 2 байта. В будущем, если будет обнаружена новая дружественная космическая колония, которая хочет общаться с ними, нам нужно будет назначить новые пионты кода Unicode для их языка и использовать больший размер символов для хранения этих строк.