首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用C预处理器将连接的字符串转换为宽字符?

如何使用C预处理器将连接的字符串转换为宽字符?
EN

Stack Overflow用户
提问于 2010-02-03 22:04:01
回答 3查看 6K关注 0票数 7

我正在做一个项目,在这个项目中,我有许多由连接(数字等)形成的常量字符串。

例如,我有一个LOCATION宏,它将__FILE____LINE__格式化为一个字符串,在打印消息或错误时,我可以使用该字符串来了解我在代码中的位置:

代码语言:javascript
运行
复制
#define _STR(x)    # x
#define STR(x)     _STR(x)
#define LOCATION __FILE__ "(" STR(__LINE__) ")"

因此,这将格式化一个类似于"file.cpp(42)“的位置。问题是当我尝试将结果转换为宽字符串时:

代码语言:javascript
运行
复制
#define _WIDEN(x)  L ## x
#define WIDEN(x)   _WIDEN(x)
#define WLOCATION  WIDEN(LOCATION)

这对于GCC来说工作得很好,结果是在我的代码中插入了L"file.cpp(42)“。但是,在使用MSVC++ (使用Visual C++ 2008学习版)尝试此操作时,我收到一个错误:

代码语言:javascript
运行
复制
error: Concatenating wide "file.cpp" with narrow "("

我知道L前缀只添加到我表达式中的第一项。我也尝试过这个:

代码语言:javascript
运行
复制
#define _WIDEN(x) L ## #x

它“工作”,但给出了字符串L"\"file.cpp\" \"(\" \"42\" \")\"",这显然不是很方便(也不是我想要的),特别是考虑到这个宏与其他宏相比很简单。

因此,我的问题是:如何将其应用于MSVC++中的整个表达式,以便我可以获得与使用GCC相同的结果?我不想创建第二个具有全宽标记的字符串,因为那样我就必须为每个标记维护两个宏,这不是很方便,而且可能会导致错误。另外,我还需要每个字符串的窄版本,所以不幸的是,使用全宽字符串也不是一种选择。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-03 23:08:02

根据C标准(又称"ISO-9899:1999“又称"C99"),Visual C是错误的,而gcc是正确的。该标准规定,第6.4.5/4节:

在转换阶段6中,由任何相邻字符序列和宽字符串文字标记指定的多字节字符序列被连接成单个多字节字符序列。如果有任何标记是宽字符串文字标记,则将生成的多字节字符序列视为宽字符串文字;否则,将其视为字符串文字。

这样你就可以投诉了。可以说,C标准的前一个版本(又称"C89“又名"C90”又名"ANSI“)并不强制将宽字符串与非宽字符串合并。虽然C99现在已经有十多年的历史了,但微软似乎对让它的C编译器符合标准没有兴趣。一些用户报告说,能够通过编译C代码来访问一些"C99“特性,就像它是C++代码一样,因为C++包括这些特性--微软为C++做出了努力。但这似乎并没有扩展到预处理器。

在C89方言中,我认为您正在寻找的东西是不可能的(实际上我非常确定,因为我已经编写了自己的预处理器,所以我认为我知道我在说什么)。但是您可以添加一个额外的参数并传播它:

代码语言:javascript
运行
复制
#define W(x)          W_(x)
#define W_(x)         L ## x
#define N(x)          x
#define STR(x, t)     STR_(x, t)
#define STR_(x, t)    t(#x)

#define LOCATION_(t)  t(__FILE__) t("(") STR(__LINE__, t) t(")")
#define LOCATION      LOCATION_(N)
#define WLOCATION     LOCATION_(W)

它应该可以在gcc和Visual C上工作(至少,它在我使用Visual C 2005的情况下可以工作)。

附注:您不应该定义名称以下划线开头的宏。这些名称是保留的,因此使用它们可能会与系统标头或编译器未来版本中使用的一些名称发生冲突。使用WIDEN_而不是_WIDEN

票数 12
EN

Stack Overflow用户

发布于 2010-02-03 22:09:29

要连接两个宽文字字符串,您可以使用

代码语言:javascript
运行
复制
L"wide_a" L"wide_b"

所以你可以定义

代码语言:javascript
运行
复制
#define WLOCATION WIDEN(__FILE__) L"(" WIDEN(STR(__LINE__)) L")"

(注意:未在MSVC++上测试)

票数 1
EN

Stack Overflow用户

发布于 2014-03-03 06:24:14

只要使用一个空的宽字符串就可以了:

代码语言:javascript
运行
复制
 #define WLOCATION L"" __FILE__ "(" STR(__LINE__) ")"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2192416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档