Я работаю над небольшим фрагментом кода, который выводит символы на экран и должен поддерживать весь Unicode, содержащийся в wchar_t, и я ограничен только записью (2).
Это проблематичное сочетание требований. В частности, представление символов wchar_t
может очень плохо сочетаться с использованием write()
для вывода.
В целом, здесь есть несколько проблем, среди них:
- Члены исходного и исполняемого наборов символов.
- Как представить расширенные символы набора символов выполнения в вашем источнике (через набор символов источника).
- Как представить расширенные символы набора символов выполнения на выбранное вами устройство вывода, чтобы это устройство обрабатывало их по желанию.
Обратите внимание, что этот C указывает только довольно небольшой набор символов, которые должны присутствовать в наборе символов выполнения. В нем могут присутствовать дополнительные, «расширенные» символы, и ваши эмодзи попадут в эту категорию. Работа с расширенными символами через стандартные интерфейсы C немного мягка, поскольку стандарт предоставляет реализациям большую свободу в том, как они там работают.
Так что \U
кажется правильным.
\U
вводит «универсальное имя персонажа». Важно понимать, что во время компиляции эти последовательности преобразуются в элементы набора символов выполнения.
Однако я не могу преобразовать wchar_t в правильную escape-последовательность, т.е. преобразовать wchar_t c =
L'????';
в \U0001f921
Небезопасно предполагать, что «????» может быть представлен непосредственно в исходном наборе символов, чтобы использовать его буквально в исходном коде. Это зависит от вашей реализации C. Универсальное имя персонажа безопаснее. Кроме того, если вам нужна константа широкого символа, вы можете попробовать L'\U0001f921'
, но есть большая вероятность, что wchar_t
не может представлять этот символ. В частности, многие реализации имеют 16-битный wchar_t
, и вряд ли они смогут поддерживать вашего персонажа как (одиночного) wchar_t
.
Возможно, вам больше повезет с широким строковым литералом: L"\U0001f921"
, но это полезно для вас, прежде всего, если вы работаете с функциями, специфичными для широких символов, которые будут выполнять соответствующие преобразования кодирования для вас. write()
не будет выполнять такие преобразования, поэтому получение желаемого результата будет зависеть от конфигурации вашей среды выполнения. Я считаю, что ваш первоначальный подход с обычным строковым литералом с большей вероятностью сработает.
Если вы хотите, и если вы можете использовать функции C2011, вы также можете выразить (обычный) строковый литерал, который определен для кодирования в UTF-8, независимо от фактического набора символов выполнения. Форма для этого будет u8"\U0001f921"
. Опять же, получение желаемого результата таким образом зависит от вашей среды. Литералы UTF-8 лучше подходят для взаимодействия с интерфейсами, которые специально определены для использования UTF-8.
Могу ли я даже сделать это в C?
Небезопасно предполагать, что ваш эмодзи может быть представлен одним объектом типа wchar_t
. Могут быть реализации C, которые его поддерживают, но я думаю, что они необычны.
Последнее замечание: этот код...
write(1, "\U0001f921", 6);
... почти наверняка демонстрирует неопределенное поведение в результате выхода за пределы массива char
, который вы представляете write()
. Я не вижу правдоподобного сценария, в котором он длиннее 5 символов, но вы пишете 6, превышая по крайней мере 1. Если внутреннее представление UTF-8, тогда этот массив будет иметь длину 4 - три байта, кодирующие символ и один для конца строки.
Вы должны измерить длину, чтобы узнать, сколько байтов нужно записать, например:
const char *emoji = "\U0001f921";
write(1, emoji, strlen(emoji));
14.12.2017
print_unicode(L'é');
, но это означает, что я не могу использовать свою удобную технику денди \Uxxxx, потому что я получаю только часть xxxx, а не полный \Uxxxx. Не уверен, что это имеет смысл... 14.12.2017wchar_t
может даже не представлять вашего конкретного персонажа. Очень похоже на то, с чем вы столкнулись. Для этого нет обходного пути, кроме перепроектирования ваших сигнатур функций. 14.12.2017