5

我有一个多平台项目,在 mac 上编译得很好,但在 windows 上,我所有带有 %s 的 swprintf 调用都在寻找 wchar_t 而不是 char * im 传递它。结果 M$ 认为让 %s 在宽字符函数中代表 char * 以外的东西会很有趣...... http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx

无论如何,我正在寻找一种创造性的编码技巧,这比在每个宽字符串调用周围都放置 ifdef else 更好

4

3 回答 3

4

更新:VS 2015 CTP6 恢复了更改,微软再次采取了与标准不同的行为。


Visual Studio 14 CTP1 及更高版本将始终%s视为窄字符串 ( char*),除非您定义_CRT_STDIO_LEGACY_WIDE_SPECIFIERS. 它还添加了 T 长度修饰符扩展,它映射到 MS 所说的“自然”宽度。对于sprintf %Tsischar*和 for swprintf %Tsis 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, %wsand %wcalways 表示wchar_tand%hs%hcare always char(此处记录了 VS2003和此处的VC6 (不确定以及何时真正添加)) %ws

在 Win9x 与 WinNT 的时代,映射%s到函数的自然宽度非常方便,通过使用tchar.h标头,您可以从同一源构建窄版本和宽版本。何时将映射中_UNICODE的函数定义为tchar.h宽函数 and TCHARis wchar_t,否则使用窄函数 and TCHARis char

_tprintf(_T("%c %s\n"), _T('a'), _T("Bcd"));

Windows SDK 头文件和其中存在的少数格式函数(wsprintf、wvsprintf、wnsprintf 和 wvnsprintf)使用了类似的约定,但它们由UNICODEandTEXT而不是_UNICODEand _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 及更早版本一起使用。

于 2012-04-03T20:54:45.763 回答
2

Use the %ls format which always means wchar_t*.

于 2012-04-03T20:25:31.237 回答
2

您可以使用“%Ts”格式说明符,也可以定义_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1。

读这个:

http://blogs.msdn.com/b/vcblog/archive/2014/06/18/crt-features-fixes-and-break-changes-in-visual-studio-14-ctp1.aspx

于 2014-11-22T00:36:42.877 回答