Suppose I need to print a formatted string with an int32_t
using the printf format specifier from <inttypes.h>
.
int32_t i = 0;
printf("%" PRId32 "\n", i);
If I try to do the same with wide characters in Visual C++ 2013, it fails:
#define W_(val) L ## val
#define W(val) W_(val)
wprintf(L"%" W(PRId32) L"\n", i);
error C2308: concatenating mismatched strings
How do I concatenate wide string literals with format conversion specifier macros?
The problem is twofold. First, as noted in rici's answer, C99 and C++11 both added support for concatenating narrow string literals and wide string literals together, so you should not need to widen the narrow literal by prepending the L. Visual C++ does not yet support this feature for either C or C++.
Because the compiler does not yet support this feature, we should in the libraries make it possible for you to explicitly widen these string literals using a technique like the one in your answer. Unfortunately, we've defined these macros in a way such that they may expand to multiple string literals. E.g., PRId32
expands to "l" "d"
.
This is valid, but it does prevent you from widening, because there is no way to prepend an L
to the second string literal (to make "d"
into L"d"
). I'm afraid I don't see a way to make this work without (re)defining the macros yourself.
I've opened a bug internally so that if the compiler does not add support for concatenation of mixed-width literals during preprocessing in the next release, we can revisit these definitions to possibly make it possible to widen them explicitly.
I know zip-all about VS C++, but you shouldn't actually need the L
prefix for the concatenand of a wide string literal.
L"%" PRId32 "\n"
should work (and it does with gcc).
From the C11 draft, §6.4.5/5: (as far as I can tell, this was roughly the same in C99, except that C99 didn't have utf-8 literals.)
In translation phase 6, the multibyte character sequences specified by any sequence of adjacent character and identically-prefixed string literal tokens are concatenated into a single multibyte character sequence. If any of the tokens has an encoding prefix, the resulting multibyte character sequence is treated as having the same prefix; otherwise, it is treated as a character string literal. Whether differently-prefixed wide string literal tokens can be concatenated and, if so, the treatment of the resulting multibyte character sequence are implementation-defined.
Also see §7.8.1/7, which provides the example:
uintmax_t i = UINTMAX_MAX; // this type always exists
wprintf(L"The largest integer value is %020"
PRIxMAX "\n", i);
A similar clause appears in the C++11 standard, §2.14.5/13. (However, in C++03, combining narrow and wide string literals was not allowed.)
In translation phase 6, adjacent string literals are concatenated. If both string literals have the same encoding-prefix, the resulting concatenated string literal has that encoding-prefix. If one string literal has no encoding-prefix, it is treated as a string literal of the same encoding-prefix as the other operand…
Apparently, Visual Studio does not allow this form of literal concatenation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With