visual studio swprintf is making all my %s formatters want wchar_t * instead of char *
printf, visual-studio
Solution
Update: VS 2015 CTP6 reverted the changes and Microsoft are yet again acting different to the standard.
Visual Studio 14 CTP1 and later will always treat `%s` as a narrow string (`char*`) unless you define `_CRT_STDIO_LEGACY_WIDE_SPECIFIERS`. It also added the T length modifier extension which maps to what MS calls the "natural" width. For `sprintf` `%Ts` is `char*` and for `swprintf` `%Ts` is `wchar_t*`.
In Visual Studio 13 and earlier `%s`/`%c` is mapped to the natural width of the function/format string and `%S`/`%C` is mapped to the opposite of the natural with:
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");
You can also force a specific width by using a length modifier: `%ls`, `%lc`, `%ws` and `%wc` always mean `wchar_t` and `%hs` and `%hc` are always `char`. (Documented for VS2003 here and VC6 here (Not sure about `%ws` and when it was really added))
Mapping `%s` to the natural width of the function was really handy back in the days of Win9x vs. WinNT, by using the `tchar.h` header you could build narrow and wide releases from the same source. When `_UNICODE` is defined the functions in `tchar.h` map to the wide functions and `TCHAR` is `wchar_t`, otherwise the narrow functions are used and `TCHAR` is `char`:
_tprintf(_T("%c %s\n"), _T('a'), _T("Bcd"));
There is a similar convention used by the Windows SDK header files and the few format functions that exist there (wsprintf, wvsprintf, wnsprintf and wvnsprintf) but they are controlled by `UNICODE` and `TEXT` and not `_UNICODE` and `_T`/`_TEXT`.
You probably have 3 choices to make a multi-platform project work on Windows if you want to support older Windows compilers:
1) Compile as a narrow string project on Windows, probably not a good idea and in your case swprintf will still treat %s as wchar_t*.
2) Use custom defines similar to how inttypes.h format strings work:
#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) Create your own custom version of swprintf and use it with Visual Studio 13 and earlier.
Problem
Ive got a multi platform project that compiles great on mac, but on windows all my swprintf calls with a %s are looking for a wchar_t instead of the char * im passing it. Turns out M$ thought it would be funny to make %s stand for something other than char * in wide character functions... http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx Anyways I'm looking for a creative coding trick thats better than putting ifdef else ends around every wide string call