如何在Visual Studio 2013中使用带有_tprintf的stdint类型?

时间:2016-12-13 16:34:31

标签: c visual-studio-2013 unicode

采用以下示例:

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?

1 个答案:

答案 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);