2015-12-04 3 views
1

В Windows есть функции, такие как mbstowcs для преобразования между char и wchar_t. Существуют также функции C++, такие как from_bytes<std::codecvt<wchar_t, char, std::mbstate_t>>.Как преобразование между char и wchar_t работает в Windows?

Но как это работает в кулисах, поскольку char и wchar_t, очевидно, имеют разный размер? Я предполагаю, что системная кодовая страница каким-то образом связана? Но что произойдет, если wchar_t не может быть скоррелирован с char (в конце концов, он может содержать намного больше значений)?

Также, что происходит, если код, который должен использовать символ (возможно, из-за библиотеки), перемещается между компьютерами с разными кодовыми страницами? Скажите, что только с использованием чисел (0-9), которые находятся в пределах диапазона ASCII, всегда будет безопасно?

И, наконец, что происходит на компьютерах, где местный язык не может быть представлен в 256 символах? В этом случае понятие char кажется совершенно несущественным, кроме как для хранения, например, utf8.

+0

'Но что произойдет, если wchar_t не может быть скоррелирован с char (в конце концов, он может содержать намного больше значений)? Это именно то, о чем нужно беспокоиться. Реальный ответ - «не конвертировать в char». Если у вас есть данные wchar_t/UTF16 и вы не хотите потерять контент, просто сохраните его как есть. (есть, конечно, другие кодировки, которые могут быть преобразованы без потерь, но обычные стандартные однобайтовые кодировки не входят в число них) – deviantfan

+0

Последний параметр Microsoft [mbstowcs] (https://msdn.microsoft.com). /en-us/library/k1f9b8cy.aspx?f=255&MSPPError=-2147217396) является [locale] (https://msdn.microsoft.com/en-us/library/wyzd2bce.aspx), который контролирует, как будет выполняться преобразование , [Стандартный] (http://en.cppreference.com/w/cpp/string/multibyte/mbstowcs) использует [setlocale] (http://en.cppreference.com/w/cpp/locale/setlocale). Это патологические. Интернационализация в любом надежном приложении должна обрабатываться специальной (Unicode) библиотекой (icu, Qt, boost, ...) – Drop

+0

О других двух проблемах, опять же, не конвертировать кодировку Unicode в 256-значный код, кодирование. – deviantfan

ответ

1

Все зависит от CVT фаски используется, как описано here

В вашем случае (std::codecvt<wchar_t, char, std::mbstate_t>) все это сводится к mbsrtowcs/wcsrtombs используя глобальную локаль. (то есть локаль «C», если вы ее не замените системным)

+0

. Интересно, так что до тех пор, пока вы не измените глобальную локаль вручную, это будет языковой стандарт C и код будет работать на любом компьютере. Тем не менее, что произойдет, если у меня есть wchar_t, который не отображается в локали C? – DaedalusAlpha

+0

В этом случае спецификация не помогает. Функция может потерпеть неудачу (и спецификации говорят, как) или * приближение * могут быть предприняты. В целом, если требуется интернационализация, лучше использовать UTF8 внутри программы и выполнять UTF8-to-16 при вызове WIN-API. Языковой стандарт C предназначен для языков программирования на английском языке. Но не более того. Язык UTF8 настолько широко признан, что все остальное скоро исчезнет (обратите внимание, что UTF8 является тем же самым ASCII в первых 127 символах, которые совпадают с языками C, поэтому формальные программы остаются теми же). –

0

Я не знаю о mbstowcs(), но я предполагаю, что он похож на std::codecvt<cT, bT, std::mbstate_t>. Последние странствия в терминах двух типов:

  • Тип характераcT, который находится в вашем коде wchar_t.
  • A байт типbT который обычно char.

Третий тип игры, std::mbstate_t, используется для хранения любого промежуточного состояния между вызовами на фасет std::codecvt<...>. Границы не могут иметь какое-либо изменчивое состояние, и любое состояние между вызовами должно быть получено каким-то образом. К сожалению, структура std::mbstate_t оставлена ​​неуказанной, то есть нет переносного способа фактически использовать ее при создании собственных граней преобразования кода.

Каждый экземпляр std::codecvt<...> реализует преобразования между байтами внешнего кодирования, например UTF8, и символы. Первоначально каждый символ предназначался как автономный объект, но различные причины (в основном извне сообщества C++, особенно из-за изменений, внесенных в Unicode) приводили к тому, что внутренние символы были фактически самими кодировками. Обычно используемые внутренние кодировки: UTF8 для char и UTF16 или UCS4 для wchar_t (в зависимости от того, использует ли wchar_t 16 или 32 бита).

Преобразования декодирования, сделанные std::codecvt<...>, принимают входящие байты во внешнем кодировании и превращают их в символы внутренней кодировки. Например, когда внешнее кодирование является UTF8, входящие байты преобразуются в 32-битные кодовые точки, которые затем застревают в символах UTF16, разбивая их до wchar_t, когда это необходимо (например, когда wchar_t - 16 бит).

Детали этого процесса не определены, но это потребует некоторой маскировки и смещения бит.Кроме того, различные преобразования будут использовать разные подходы. Если сопоставление между внешней и внутренней кодировкой не так тривиально, как отображение одного представления Unicode в другое представление, могут быть подходящие таблицы, обеспечивающие фактическое сопоставление.

0

я, что вмассив символов является фактически UTF-8 строка в кодировке, то вы можете преобразовать его в и из массива wchar_t UTF-16, закодированные с помощью

#include <locale> 
#include <codecvt> 
#include <string> 

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; 
std::string narrow = converter.to_bytes(wide_utf16_source_string); 
std::wstring wide = converter.from_bytes(narrow_utf8_source_string); 

, как описано в более подробно на https://stackoverflow.com/a/18597384/6345

Смежные вопросы