Введение
Тип данных
Вариации символов ASCII двойной ширины (размера иероглифов CJK).
double wide (CJK ideograph sized) variations of ASCII characters
Широкий символ – это компьютерный тип данных символа, который, как правило, имеет размер больше, чем традиционный 8-битный символ. Увеличенный размер типа данных позволяет использовать более крупные наборы закодированных символов.
История
В 1960-х годах производители мейнфреймов и мини-компьютеров начали стандартизировать 8-битный байт как свой наименьший тип данных. 7-битный набор символов ASCII стал отраслевым стандартом для кодирования алфавитно-цифровых символов в телетайпах и компьютерных терминалах. Дополнительный бит использовался для контроля четности, чтобы обеспечить целостность хранения и передачи данных. В результате 8-битный байт стал де-факто типом данных для компьютерных систем, хранящих символы ASCII в памяти. Позже производители компьютеров начали использовать освободившийся бит для расширения набора символов ASCII за пределы ограниченного набора символов английского алфавита. 8-битные расширения, такие как IBM code page 37, PETSCII и ISO 8859, стали широко распространены, обеспечивая поддержку терминалов для греческого, кириллицы и многих других языков. Однако эти расширения оставались ограниченными, поскольку были привязаны к конкретным регионам и часто не могли использоваться совместно. Для преобразования из одного набора символов в другой требовались специальные процедуры, которые часто приводили к потере информации при отсутствии эквивалентного символа в целевом наборе. В 1989 году Международная организация по стандартизации начала разработку Универсального набора символов (UCS) – многоязычного набора символов, который можно было кодировать с использованием 16 бит (2 байта) или 32 бит (4 байта). Для хранения этих больших значений в памяти требовался тип данных, превышающий 8 бит. Поэтому для их обозначения был введен термин "широкий символ", чтобы отличать их от традиционных 8-битных типов данных символов.
Отношение к UCS и Unicode
Широкий символ относится к размеру типа данных в памяти. Он не определяет, как конкретно определено каждое значение в наборе символов. Эти значения определяются посредством использования наборов символов, при этом UCS и Unicode являются лишь двумя распространенными наборами символов, которые кодируют больше символов, чем это возможно при использовании 8-битного числового значения (всего 255).
Отношение к многобайтовым символам
Как и более ранние системы передачи данных страдали от отсутствия чистого 8-битного канала для данных, так и современные системы передачи часто не поддерживают 16-битные или 32-битные каналы для данных символов. Это привело к появлению систем кодирования символов, таких как UTF-8, которые могут использовать несколько байтов для кодирования значения, превышающего размер одного 8-битного символа. Стандарт C различает многобайтовые кодировки символов, использующие фиксированное или переменное число байтов для представления каждого символа (преимущественно в исходном коде и внешних файлах), и символы широкого формата, которые являются представлениями символов в виде отдельных объектов во время выполнения (как правило, больше 8 бит).
Размер широкого символа
Раннее внедрение UCS-2 ("Unicode 1.0") привело к широкому распространению UTF-16 на ряде платформ, наиболее заметно в Microsoft Windows, .NET и Java. В этих системах обычно используется "широкий символ" (в C/C++; в Java) размером 16 бит. Эти типы не всегда соответствуют одному "символу", так как для хранения полного диапазона Unicode (1996, Unicode 2.0) требуются суррогатные пары. Системы, подобные Unix, как правило, используют 32-битное представление для соответствия 21-битным кодовым точкам Unicode, как это предписывалось стандартом C90. Размер типа "широкий символ" не определяет, какие текстовые кодировки может обрабатывать система, поскольку доступны преобразования. (Однако старый код преобразования часто не учитывает суррогаты.) Исторические обстоятельства внедрения также влияют на предпочтительные типы кодирования. Система, испытавшая влияние Unicode 1.0, такая как Windows, как правило, в основном использует "широкие строки", состоящие из широких символов. Другие системы, такие как Unix, напротив, обычно сохраняют 8-битовую "узкую строку", используя многобайтовую кодировку (почти повсеместно UTF-8) для обработки "широких" символов.
C/C++
Стандартные библиотеки C и C++ включают ряд средств для работы с широкими символами и строками, состоящими из них. Широкие символы определяются с использованием типа данных `wchar_t`, который в оригинальном стандарте C90 был определен как
"целочисленный тип, диапазон значений которого может представлять различные коды для всех членов наибольшего расширенного набора символов, указанного среди поддерживаемых локалей" (ISO 9899:1990 §4.1.5).
И C, и C++ в пересмотре 2011 года своих стандартов ввели типы символов фиксированного размера `char16_t` и `char32_t` для обеспечения однозначного представления 16-битных и 32-битных форматов преобразования Unicode, оставив реализацию `wchar_t` определяемой компилятором. В стандарте ISO/IEC 10646:2003 Unicode 4.0 говорится:
"Ширина `wchar_t` зависит от компилятора и может быть не меньше 8 бит. Следовательно, программы, которым требуется переносимость между различными компиляторами C или C++, не должны использовать `wchar_t` для хранения текста Unicode. Тип `wchar_t` предназначен для хранения широких символов, определенных компилятором, которые в некоторых компиляторах могут быть символами Unicode."
Python (англ.)
Согласно документации Python 2.7, язык иногда использует `wchar_t` в качестве основы для своего типа символов `Py_UNICODE`. Это зависит от того, является ли `wchar_t` "совместимым с выбранным вариантом сборки Python Unicode" в данной системе. Это различие устарело, начиная с Python 3.3, который представил хранилище UCS1/2/4 переменного размера для строк и формально приравнял его к `wchar_t`. Начиная с Python 3.12, использование `wchar_t`, то есть `Py_UNICODE typedef`, для строк Python (wstr в реализации) было отменено, и по-прежнему, как и прежде, "представление UTF-8 создается по требованию и кэшируется в объекте Unicode".