Что такое __wchar_t и почему я получаю ошибки, связанные с этим?
Компилятор Microsoft Visual C++ имеет параметр с названием /Zc:wchar_t, который позволяет управлять значением wchar_t.
Согласно стандартам в C++, wchar_t является отдельным типом, что компилятор Visual C++ использует по умолчанию. Тем не менее, вы можете использовать /Zc:wchar_t, что позволит определять wchar_t так, как вам нужно. В Windows это исторически обозначается, как
typedef unsigned short wchar_t;
, потому что Windows предшествует версиям C и C++, в которых wch
ar_t вводится в качестве собственного типа.
Проблема возникает, если вы пишите библиотеку, которая будет пользоваться как старым кодом, так и новым. Какой тип данных вы используете для строковых параметров?
Что ж, если ваша библиотека привязана к C, то вам повезло. Встроенный wchar_t представляет собой 16-разрядное целое число без знака в Visual C++, что совместимо с двоичными данными с unsigned short, поэтому вы можете объявить свою функцию как принимающую wchar_t в заголовочном файле и каждый клиент сможет интерпретировать её через собственный wchar_t-color: Код /Zc:wchar_t будет видеть собственный wchar_t. Код /Zc:wchar_t- увидит unsigned short. А в C вы сможете экспортировать функцию, которая примет значение wchar_t.
Это работает для недекорированных функций, но как насчет C++, который использует декорирование для кодирование типов параметров? Что же использовать?
Попробуйте написать две версии вашей функции, одна будет использовать unsigned short, а другая - __wchar_t.
Другими словами, /Zc:wchar_t приводит к тому, что компилятор внутри делает эквивалент:
typedef __wchar_t wchar_t;
Оно делает символ wchar_t псевдонимом для внутреннего типа __wchar_t.
Допустим, у вас есть функция DoSomething, которая использует широкую строку и вы хотите принимать клиентов, скомпилированных с любым параметром для /Zc:wchar_t.
// Something.h bool DoSomething(const __wchar_t* s); bool DoSomething(const unsigned short* s);
Оно объявляет две версии функции. Первой будет соответствовать код, скомпилированный из /Zc:wchar_t. Второй будет скомпилирован из /Zc:wchar_t-.
Это будет выглядеть так:
// Something.cpp #include <Something.h> bool DoSomethingWorker(const wchar_t* s) { ... implementation ... } bool DoSomething(const __wchar_t* s) { return DoSomethingWorker(reinterpret_cast<const wchar_t*>(s)); } bool DoSomething(const unsigned short* s) { return DoSomethingWorker(reinterpret_cast<const wchar_t*>(s)); }
Как отмечалось ранее, вызов программы, компилирующей /Zc:wchar_t будет соответствовать первой версии DoSomething, а /Zc:wchar_t- - второй. Но оба они объединяются, образуя wchar_t, так что она соответствует настройке /Zc:wchar_t, которая используется библиотекой.
Итак __wchar_t - это имя внутреннего типа данных для широких строк. Если вы компилируете с /Zc: wchar_t, то этот тип данных wchar_t. Забавное имя существует для того, чтобы код, скомпилированный с /Zc: wchar_t-, мог также получить к нему доступ, и чтобы код / Zc: wchar_t-agnostic, мог ссылаться на внутренний нативный тип.
Перевод: https://devblogs.microsoft.com/oldnewthing/20161201-00/?p=94836