Я получаю необъяснимые сбои (возвращаемое значение -1) от vswprintf
с использованием GCC и Mac OS X (протестировано с gcc 4.0 и 4.2.1 под Mac OS X 10.6 и 10.8. GCC под Linux не пострадавшие. Visual Studio также не пострадавших).
Чтобы продемонстрировать проблему, я минимально адаптировал пример из Вот так что распечатывает vswprintf
возвращаемое значение:
/* vswprintf example */
#include <stdio.h>
#include <stdarg.h>
#include <wchar.h>
void PrintWide ( const wchar_t * format, ... )
{
wchar_t buffer[256];
va_list args;
va_start ( args, format );
int res = vswprintf ( buffer, 256, format, args );
wprintf ( L"result=%d\n", res );
fputws ( buffer, stdout );
va_end ( args );
}
int main ()
{
wchar_t str[] = L"test string has %d wide characters.\n";
PrintWide ( str, wcslen(str) );
return 0;
}
Из моих тестов выясняется, что в зависимости от значения str
, vswprintf
иногда потерпит неудачу. Примеры:
wchar_t str[] = L"test string has %d wide characters.\n"; // works
wchar_t str[] = L"ßß® test string has %d wide characters.\n"; // works
wchar_t str[] = L"日本語 test string has %d wide characters.\n"; // FAILS
wchar_t str[] = L"Π test string has %d wide characters.\n"; // FAILS
wchar_t str[] = L"\u03A0 test string has %d wide characters.\n"; // FAILS
Похоже, что любые строки, которые включают символы с кодами Unicode выше 0xff
вызовет эту проблему. Кто-нибудь может пролить свет на то, почему это происходит? Кажется, это слишком большая проблема, чтобы не было замечено раньше!
Если вы установите язык, это должно быть хорошо. Чтобы подобрать переменную среды, вы можете сделать это:
setlocale(LC_CTYPE, ""); // include <locale.h>
или установите это явно. Это потому, что все выходные функции должны знать, какую кодировку использовать.
OS X не может выполнить vswprintf
вообще, пока Linux запускает его (хотя символы будут неправильными, если будут напечатаны).
Вот соответствующий раздел документации glibc:
If the format string contains non-ASCII wide characters, the program will only work correctly if the LC_CTYPE category of the current locale at run time is the same as the LC_CTYPE category of the current locale at compile time. This is because the wchar_t representation is plat‐ form- and locale-dependent. (The glibc represents wide characters using their Unicode (ISO-10646) code point, but other platforms don't do this.
Других решений пока нет …