采用以下示例:
char* fileName = "C:\\windows\\system32\\kernel32.dll";
uint32_t fileSize = 1163264;
printf("The size of %s is %"PRIu32"\n", fileName, fileSize);
一切都很好,现在如果我们想通过tchar.h
获得透明的unicode支持,代码将如下所示:
TCHAR* fileName = _T("C:\\windows\\system32\\kernel32.dll");
uint32_t fileSize = 1163264;
_tprintf(_T("The size of %s is %")_T(PRIu32)_T("\n"), fileName, fileSize);
如果unicode 不已定义,则此方法有效。但是,如果定义了unicode,编译器将中止并出现以下错误:
error C2308: concatenating mismatched strings
Concatenating wide "The size of %s is %l" with narrow "u"
现在看看微软的inttypes.h,我看到了:
...
#define _PFX_32 "l"
...
#define PRIu32 _PFX_32 "u"
这意味着上例中的_T(PRIu32)
解析为:
_T("l" "u")
...当然无法正常工作并解释了正确的编译错误。
因此我的问题是微软是如何想象我们使用他们的inttypes.h定义的_tprintf?
答案 0 :(得分:4)
根据 1 到当前的C标准,只有一个字符序列(读作:字符串)必须以编码前缀作为前缀,其余的字符序列被视为具有相同的前缀,并连接成一个字符串。
编码前缀由_T宏决定。如果未定义UNICODE,它将解决为空,否则它将在L
前加上参数。
解决方案是在第一个字符串上使用_T宏,其余部分没有宏,并且它们将使用相同的编码:
_tprintf(_T("The size of %s is %") PRIu32 "\n", fileName, fileSize);
但您使用的Visual Studio版本不符合C99,因此缺少此功能。看起来这已在Visual Studio 2015中修复。
标准中的示例 2 证明了相同的用法。
1 (引自:ISO / IEC 9899:201x 6.4.5字符串文字5)
在翻译阶段6中,由任何序列指定的多字节字符序列
相邻字符和相同前缀的字符串文字标记连接成一个
单个多字节字符序列。如果任何令牌具有编码前缀,则
产生的多字节字符序列被视为具有相同的前缀;否则,它
被视为字符串文字。是否有不同的前缀宽字符串文字
令牌可以连接,如果是,则可以处理生成的多字节字符
序列是实现定义的。
2 (引自:ISO / IEC 9899:201x 7.8.1格式说明符7的宏)
wprintf(L"The largest integer value is %020" PRIxMAX "\n", i);