Набор символов Visual Studio "Не задан" vs "Набор символов с несколькими байтами"

Я работаю с устаревшим приложением, и я пытаюсь разобраться в различиях между приложениями, скомпилированными с Multi byte character set и Not Set под опцией Character Set.

Я понимаю, что компиляция с Multi byte character set определяет _MBCS, которая позволяет использовать многобайтовые коды кодовых страниц, и использование Not Set не определяет _MBCS, и в этом случае только однобайтовые коды символов разрешены.

В том случае, когда используется Not Set, я предполагаю, что мы можем использовать только однобайтовые коды символов, найденные на этой странице: http://msdn.microsoft.com/en-gb/goglobal/bb964654.aspx

Поэтому я правильно понимаю, что используется Not Set, приложение не сможет кодировать и писать или читать языки дальнего востока, поскольку они определены в двухбайтовых наборах символов (и, конечно, Unicode )?

В соответствии с этим, если определено Multi byte character set, доступны ли как одиночные, так и многобайтовые кодовые страницы набора символов или только многобайтовые кодовые страницы набора символов? Я предполагаю, что он должен поддерживаться как для европейских языков.

Спасибо,

Andy

Дополнительная литература

Ответы на этих страницах не отвечали на мой вопрос, но помогли в моем понимании: О наборе символов " вариант в visual studio 2010

Исследование

Итак, так же, как и работая с исследованием... С моей локалью, установленной как японский

Влияние на строковые кодированные строки

char *foo = "Jap text: テスト";
wchar_t *bar = L"Jap text: テスト";

Компиляция с помощью Unicode

* foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (кодовая страница 932)
* bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16 или UCS-2

Компиляция с Multi byte character set

* foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (кодовая страница 932)
* bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16 или UCS-2

Компиляция с Not Set

* foo = 4a 61 70 20 74 65 78 74 3a 20 83 65 83 58 83 67 == Shift-Jis (кодовая страница 932)
* bar = 4a 00 61 00 70 00 20 00 74 00 65 00 78 00 74 00 3a 00 20 00 c6 30 b9 30 c8 30 == UTF-16 или UCS-2

Вывод: Кодировка символов не влияет на строчные кодированные строки. Хотя определение символов, как указано выше, похоже, использует кодировку Locale, и wchar_t, похоже, использует либо UCS-2, либо UTF-16.

Использование закодированных строк в W/A версиях API Win32

Итак, используя следующий код:

char *foo = "C:\\Temp\\テスト\\テa.txt";
wchar_t *bar = L"C:\\Temp\\テスト\\テw.txt";

CreateFileA(bar, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CreateFileW(foo, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

Компиляция с помощью Unicode

Результат: оба файла созданы

Компиляция с Multi byte character set

Результат: оба файла созданы

Компиляция с Not Set

Результат: оба файла созданы

Вывод: Обе версии API A и W предполагают такую ​​же кодировку независимо от выбранного набора символов. Из этого, возможно, мы можем предположить, что все опции Character Set - это переключение между версией API. Таким образом, версия A всегда ожидает строки в кодировке текущей кодовой страницы, а версия W всегда ожидает UTF-16 или UCS-2.

Открытие файлов с использованием W и A Win32 API

Итак, используя следующий код:

char filea[MAX_PATH] = {0};
OPENFILENAMEA ofna = {0};
ofna.lStructSize = sizeof ( ofna );
ofna.hwndOwner = NULL  ;
ofna.lpstrFile = filea ;
ofna.nMaxFile = MAX_PATH;
ofna.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofna.nFilterIndex =1;
ofna.lpstrFileTitle = NULL ;
ofna.nMaxFileTitle = 0 ;
ofna.lpstrInitialDir=NULL ;
ofna.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;  

wchar_t filew[MAX_PATH] = {0};
OPENFILENAMEW ofnw = {0};
ofnw.lStructSize = sizeof ( ofnw );
ofnw.hwndOwner = NULL  ;
ofnw.lpstrFile = filew ;
ofnw.nMaxFile = MAX_PATH;
ofnw.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofnw.nFilterIndex =1;
ofnw.lpstrFileTitle = NULL;
ofnw.nMaxFileTitle = 0 ;
ofnw.lpstrInitialDir=NULL ;
ofnw.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;

GetOpenFileNameA(&ofna);
GetOpenFileNameW(&ofnw);

и выбрав либо:

  • C:\Temp\テ ス ト\テ openw.txt
  • C:\Temp\テ ス ト\テ openw.txt

Урожайность:

При компиляции с Unicode

* filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis (кодовая страница 932)
* filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 или UCS-2

При компиляции с Multi byte character set

* filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis (кодовая страница 932)
* filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 или UCS-2

При компиляции с Not Set

* filea = 43 3a 5c 54 65 6d 70 5c 83 65 83 58 83 67 5c 83 65 6f 70 65 6e 61 2e 74 78 74 == Shift-Jis (кодовая страница 932)
* filew = 43 00 3a 00 5c 00 54 00 65 00 6d 00 70 00 5c 00 c6 30 b9 30 c8 30 5c 00 c6 30 6f 00 70 00 65 00 6e 00 77 00 2e 00 74 00 78 00 74 00 == UTF-16 или UCS-2

Вывод: Опять же, параметр Character Set не влияет на поведение Win32 API. Версия A всегда возвращает строку с кодировкой активной кодовой страницы, а W всегда возвращает UTF-16 или UCS-2. Я действительно могу это объяснить в этом замечательном ответе: qaru.site/info/103552/....

Окончательное сокрушение

Ганс кажется правильным, когда говорит, что у определения нет на него никакой магии, кроме изменения API Win32, чтобы использовать либо W, либо A. Поэтому я не вижу никакой разницы между Not Set и Multi byte character set.

Ответ 1

Нет, это не так, как это работает. Единственное, что происходит, это то, что макрос определяется, он иначе не оказывает волшебного эффекта на компилятор. Очень редко писать код, который использует #ifdef _MBCS для проверки этого макроса.

Вы почти всегда оставляете это до вспомогательной функции для преобразования. Подобно WideCharToMultiByte(), OLE2A() или wctombs(). Которые являются функциями преобразования, которые всегда учитывают многобайтовые кодировки, руководствуясь кодовой страницей. _MBCS - историческая авария, актуальная только 25 лет назад, когда многобайтовые кодировки не были распространены. Подобным образом использование кодировки, отличной от Юникода, является историческим артефактом и в наши дни.

Ответ 2

В ссылка указано, что:

По определению набор символов ASCII является подмножеством всех многобайтовые символы. Во многих многобайтовых наборах символов каждый символ в диапазоне 0x00 - 0x7F идентичен характеру, который имеет такое же значение в наборе символов ASCII. Например, в обоих случаях ASCII и символьные строки MBCS, 1-байтовый символ NULL ('\ 0') имеет значение 0x00 и указывает завершающий нулевой символ.

Как вы уже догадались, включив _MBCS Visual Studio также поддерживает одиночный набор символов ASCII.

В секунду ссылка один набор символов, кажется, поддерживается, даже если мы включили _MBCS:

Переносимость MBCS/Unicode: Используя заголовочный файл Tchar.h, вы можете создать однобайтовые, MBCS и Unicode-приложения из одних и тех же источников. Tchar.h определяет макросы с префиксом _tcs, которые сопоставляются с str, _mbs или wcs, в зависимости от ситуации. Чтобы создать MBCS, определите символ _MBCS. Чтобы создать Unicode, определите символ _UNICODE. По умолчанию _MBCS определенных для приложений MFC. Для получения дополнительной информации см. Общий текст Отображения в Tchar.h.