我有一个多平台项目,在 mac 上编译得很好,但在 windows 上,我所有带有 %s 的 swprintf 调用都在寻找 wchar_t 而不是 char * im 传递它。结果 M$ 认为让 %s 在宽字符函数中代表 char * 以外的东西会很有趣...... http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx
无论如何,我正在寻找一种创造性的编码技巧,这比在每个宽字符串调用周围都放置 ifdef else 更好
我有一个多平台项目,在 mac 上编译得很好,但在 windows 上,我所有带有 %s 的 swprintf 调用都在寻找 wchar_t 而不是 char * im 传递它。结果 M$ 认为让 %s 在宽字符函数中代表 char * 以外的东西会很有趣...... http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx
无论如何,我正在寻找一种创造性的编码技巧,这比在每个宽字符串调用周围都放置 ifdef else 更好
更新:VS 2015 CTP6 恢复了更改,微软再次采取了与标准不同的行为。
Visual Studio 14 CTP1 及更高版本将始终%s
视为窄字符串 ( char*
),除非您定义_CRT_STDIO_LEGACY_WIDE_SPECIFIERS
. 它还添加了 T 长度修饰符扩展,它映射到 MS 所说的“自然”宽度。对于sprintf
%Ts
ischar*
和 for swprintf
%Ts
is wchar_t*
。
在 Visual Studio 13 和更早版本中, %s
/%c
映射到函数/格式字符串的自然宽度,并且%S
/%C
映射到与自然相反的宽度:
printf("%c %C %s %S\n", 'a', L'B', "cd", L"EF");
wprintf(L"%c %C %s %S\n", L'a', 'B', L"cd", "EF");
您还可以通过使用长度修饰符来强制指定宽度:%ls
, %lc
, %ws
and %wc
always 表示wchar_t
and%hs
和%hc
are always char
。(此处记录了 VS2003和此处的VC6 (不确定以及何时真正添加)) %ws
在 Win9x 与 WinNT 的时代,映射%s
到函数的自然宽度非常方便,通过使用tchar.h
标头,您可以从同一源构建窄版本和宽版本。何时将映射中_UNICODE
的函数定义为tchar.h
宽函数 and TCHAR
is wchar_t
,否则使用窄函数 and TCHAR
is char
:
_tprintf(_T("%c %s\n"), _T('a'), _T("Bcd"));
Windows SDK 头文件和其中存在的少数格式函数(wsprintf、wvsprintf、wnsprintf 和 wvnsprintf)使用了类似的约定,但它们由UNICODE
andTEXT
而不是_UNICODE
and _T
/控制_TEXT
。
如果您想支持较旧的 Windows 编译器,您可能有 3 个选择来使多平台项目在 Windows 上运行:
1)在 Windows 上编译为窄字符串项目,这可能不是一个好主意,在您的情况下,swprintf 仍会将 %s 视为 wchar_t*。
2)使用类似于 inttypes.h 格式字符串工作方式的自定义定义:
#ifdef _WIN32
#define PRIs "s"
#define WPRIs L"hs"
#else
#define PRIs "s"
#define WPRIs L"s"
#endif
printf("%" PRIs " World\n", "Hello");
wprintf(L"%" WPRIs L" World\n", "Hello");
3)创建您自己的自定义版本的 swprintf 并将其与 Visual Studio 13 及更早版本一起使用。
Use the %ls
format which always means wchar_t*
.
您可以使用“%Ts”格式说明符,也可以定义_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1。
读这个: