假设我需要使用int32_t
中的printf格式说明符打印带<inttypes.h>
的格式化字符串。
int32_t i = 0;
printf("%" PRId32 "\n", i);
如果我尝试在Visual C ++ 2013中对宽字符执行相同操作,则会失败:
#define W_(val) L ## val
#define W(val) W_(val)
wprintf(L"%" W(PRId32) L"\n", i);
错误C2308:连接不匹配的字符串
如何将宽字符串文字与格式转换说明符宏连接?
答案 0 :(得分:5)
问题是双重的。首先,正如rici的回答所述,C99和C ++ 11都支持将窄字符串文字和宽字符串文字连接在一起,所以你不需要通过在L之前加宽来扩展窄文字.Visual C ++还不支持这个C或C ++的功能。
因为编译器还不支持此功能,所以我们应该在库中使您可以使用类似答案的技术显式扩展这些字符串文字。不幸的是,我们已经定义了这些宏,以便它们可以扩展为多个字符串文字。例如,PRId32
扩展为"l" "d"
。
这是有效的,但它确实会阻止您扩大,因为无法将L
添加到第二个字符串文字(将"d"
添加到L"d"
)。如果没有(重新)自己定义宏,我恐怕没有办法让这项工作成功。
我在内部打开了一个错误,因此如果编译器在下一个版本的预处理期间没有添加对混合宽度文字串联的支持,我们可以重新访问这些定义,以便可以明确地扩展它们。
答案 1 :(得分:1)
我知道有关VS C ++的zip-all,但实际上你不应该为宽字符串文字的concatenand提供L
前缀。
L"%" PRId32 "\n"
应该有效(和gcc一样)。
从C11草案,§6.4.5/ 5 :(据我所知,这在C99中大致相同,只是C99没有utf-8文字。)
在翻译阶段6中,由任何序列指定的多字节字符序列 相邻字符和相同前缀的字符串文字标记连接成一个 单个多字节字符序列。如果任何令牌具有编码前缀,则 产生的多字节字符序列被视为具有相同的前缀;否则,它 被视为字符串文字。是否有不同的前缀宽字符串文字 令牌可以连接,如果是,则可以处理生成的多字节字符 序列是实现定义的。
另见§7.8.1/ 7,其中提供了示例:
uintmax_t i = UINTMAX_MAX; // this type always exists
wprintf(L"The largest integer value is %020"
PRIxMAX "\n", i);
类似的条款出现在C ++ 11标准§2.14.5/ 13中。 (但是,在C ++ 03中,不允许组合窄字符串和宽字符串文字。)
在翻译阶段6中,连接相邻的字符串文字。如果两个字符串文字具有相同的encoding-prefix,则生成的连接字符串文字具有该encoding-prefix。如果一个字符串文字没有编码前缀,则将其视为与另一个操作数相同的编码前缀的字符串文字...
显然,Visual Studio不允许这种形式的文字连接。