如何使用C预处理器将连接的字符串转换为宽字符? [英] How to convert concatenated strings to wide-char with the C preprocessor?

查看:234
本文介绍了如何使用C预处理器将连接的字符串转换为宽字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a project where I have many constant strings formed by concatenation (numbers, etc.).

例如,我有一个 LOCATION 宏格式化为 __ FILE __ __ LINE __ 知道我在代码中的位置,当打印消息或错误时:

For example, I have a LOCATION macro that formats __FILE__ and __LINE__ into a string that I can use to know where I am in the code, when printing messages or errors:

#define _STR(x)    # x
#define STR(x)     _STR(x)
#define LOCATION __FILE__ "(" STR(__LINE__) ")"

所以,这将格式化一个位置像file.cpp(42)。问题是当我尝试将结果转换为宽字符串:

So, this would format a location like "file.cpp(42)". The problem is when I try to convert the result to a wide-string:

#define _WIDEN(x)  L ## x
#define WIDEN(x)   _WIDEN(x)
#define WLOCATION  WIDEN(LOCATION)


$ b b

这对GCC工作正常,导致在我的代码中插入Lfile.cpp(42)。但是,当使用MSVC ++(使用Visual C ++ 2008 Express)尝试此操作时,会出现错误:

This works just fine with GCC, and results in L"file.cpp(42)" being inserted in my code. However, when trying this with MSVC++ (using Visual C++ 2008 Express), I get an error:

error: Concatenating wide "file.cpp" with narrow "("

我理解 code>前缀只添加到我的表达式中的第一个词。我也尝试过:

I understand that the L prefix gets added only to the first term in my expression. I've also tried this:

#define _WIDEN(x) L ## #x

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

Which "works", but gives the string L"\"file.cpp\" \"(\" \"42\" \")\"" which is obviously not very convenient (and not what I am looking for), especially considering that this macro is simple compared to other macros.

所以,我的问题是,如何得到它应用于在MSVC ++中的整个表达式,所以我可以得到相同的结果我得到与GCC?我宁愿不创建第二个字符串与全宽的令牌,因为我将为每个维护两个宏,这不是很方便,并且可能导致错误。另外,我需要每个字符串的窄版本,所以使用全宽字符串不是一个选择,不幸的是。

So, my question is: how can I get it to apply to the entire expression in MSVC++, so I can get the same result I am getting with GCC? I would rather not create a second string with all-wide tokens, because I would then have to maintain two macros for each one, which is not very convenient and can lead to bugs. Plus, I need the narrow version of each string as well, so using all-wide strings is not an option either, unfortunately.

推荐答案

根据C标准(又名ISO-9899:1999又名C99),Visual C是错误的,gcc是正确的。该标准陈述了第6.4.5 / 4节:

According to the C standard (aka "ISO-9899:1999" aka "C99"), Visual C is wrong and gcc is correct. That standard states, section 6.4.5/4:

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

因此,您可以提出投诉。可以说,以前版本的C标准(也称为C89又名C90又名ANSI C)没有要求合并宽字符串与非宽字符串。虽然C99现在已经十多年了,但似乎微软没有兴趣使其C编译器符合。一些用户已经报告能够通过编译C代码来访问一些C99功能,就像它是C ++代码一样,因为C ++包括这些功能,而对于C ++,Microsoft做出了努力。但这似乎不扩展到预处理器。

So you could file a complaint. Arguably, the previous version of the C standard (aka "C89" aka "C90" aka "ANSI C") did not mandate merging of wide strings with non-wide strings. Although C99 is now more than ten years old, it seems that Microsoft has no interest in making its C compiler conforming. Some users have reported being able to access some "C99" features by compiling C code as if it was C++ code, because C++ includes these features -- and for C++, Microsoft made an effort. But this does not seem to extend to the preprocessor.

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

In the C89 dialect, I think that what you are looking for is not possible (actually I am pretty sure of it, and since I have written my own preprocessor I think I know what I am talking about). But you could add an extra parameter and propagate it:

#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)

C(至少,它适用于我,使用Visual C 2005)。

which should work on both gcc and Visual C (at least, it works for me, using Visual C 2005).

注意:你不应该定义名称以下划线开头的宏。这些名称是保留的,因此使用它们可能会与系统头或未来版本的编译器中使用的某些名称冲突。而不是 _WIDEN ,请使用 WIDEN _

Side note: you should not define macros with a name beginning with an underscore. These names are reserved, so by using them you could clash with some names used in system headers or in future versions of the compiler. Instead of _WIDEN, use WIDEN_.

这篇关于如何使用C预处理器将连接的字符串转换为宽字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆