C++ 对于Mac OS X下的某些unicode代码点,vswprintf失败
使用GCC和Mac OS X(在Mac OS X 10.6和10.8下使用GCC 4.0和4.2.1进行测试。Linux下的GCC未受影响。Visual Studio也未受影响) 为了演示这个问题,我对示例进行了最低限度的修改,以便它打印出C++ 对于Mac OS X下的某些unicode代码点,vswprintf失败,c++,c,macos,gcc,darwin,C++,C,Macos,Gcc,Darwin,使用GCC和Mac OS X(在Mac OS X 10.6和10.8下使用GCC 4.0和4.2.1进行测试。Linux下的GCC未受影响。Visual Studio也未受影响) 为了演示这个问题,我对示例进行了最低限度的修改,以便它打印出vswprintf的返回值: /* vswprintf example */ #include <stdio.h> #include <stdarg.h> #include <wchar.h> void PrintWide
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;
}
任何包含Unicode代码点高于
0xff
的字符的字符串都会触发此问题。有人能解释为什么会发生这种情况吗?这似乎是一个太大的问题,以前从未被注意过 如果您设置了区域设置,应该可以。要选择环境变量,可以执行以下操作:
setlocale(LC_CTYPE, ""); // include <locale.h>
源文件的编码是否与字符串中预期的编码匹配?我希望
fputws
调用在超出范围字符的默认“C”
区域设置中失败,但是vswprintf
应该可以工作。没有标题所说的“GCC-vswprintf”。GNU/Linux上的GCC与Mac OS X上的GCC行为不同的原因在于vswprintf
与GCC无关,它由操作系统的C库libc
提供,谢谢。我已经相应地修改了标题。实际上,在我看来,vswprintf
调用不应该受到语言环境的影响,但是fputsw
调用应该会失败……你的确是对的!顺便说一句,在Ubuntu11.04下,调用不仅成功,而且即使没有设置语言环境,输出也是正确的。@Xaxx-很高兴它有帮助。我认为Ubuntu11.04必须更加宽容。我在Ubuntu12.10中尝试过,但它给出了错误的字符(手册页上说必须设置LC_CTYPE)。@teppic-我应该更精确一些。在Ubuntu下,vswprintf
调用成功,结果缓冲区被正确的代码点填充。但是,如果您随后尝试打印出来(例如,使用printf),则除非设置了LC_CTYPE,否则输出将不正确。@Xaxx-ah我明白了。我没有在12点10分检查。但是是的,在OSX上,调用完全失败,即使使用ASCII。
setlocale(LC_CTYPE, ""); // include <locale.h>
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.