## 预处理器运算符的应用和需要考虑的问题是什么? [英] What are the applications of the ## preprocessor operator and gotchas to consider?
问题描述
正如我之前的许多问题中所提到的,我正在使用 K&R,目前正在使用预处理器.更有趣的事情之一—从我之前尝试学习 C 的任何尝试中我从未知道的东西 -mdash;是 ##
预处理器运算符.根据 K&R:
As mentioned in many of my previous questions, I'm working through K&R, and am currently into the preprocessor. One of the more interesting things — something I never knew before from any of my prior attempts to learn C — is the ##
preprocessor operator. According to K&R:
预处理操作符##
提供了一种连接实际的方法宏扩展期间的参数.如果一个替换文本中的参数是与 ##
相邻,参数为替换为实际参数,##
和周围的空白是删除,并重新扫描结果.例如,宏 paste
连接它的两个参数:
The preprocessor operator
##
provides a way to concatenate actual arguments during macro expansion. If a parameter in the replacement text is adjacent to a##
, the parameter is replaced by the actual argument, the##
and surrounding white space are removed, and the result is re-scanned. For example, the macropaste
concatenates its two arguments:
#define paste(front, back) front ## back
so paste(name, 1)
创建令牌name1
.
有人会如何以及为什么会在现实世界中使用它?它的使用有哪些实际例子,是否有需要考虑的问题?
How and why would someone use this in the real world? What are practical examples of its use, and are there gotchas to consider?
推荐答案
CrashRpt:使用##将宏多字节字符串转换为Unicode
CrashRpt(崩溃报告库)中一个有趣的用法如下:
An interesting usage in CrashRpt (crash reporting library) is the following:
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
//Note you need a WIDEN2 so that __DATE__ will evaluate first.
这里他们想使用一个两字节的字符串,而不是一个每字符一个字节的字符串.这可能看起来真的毫无意义,但他们这样做是有充分理由的.
Here they want to use a two-byte string instead of a one-byte-per-char string. This probably looks like it is really pointless, but they do it for a good reason.
std::wstring BuildDate = std::wstring(WIDEN(__DATE__)) + L" " + WIDEN(__TIME__);
他们将它与另一个返回带有日期和时间的字符串的宏一起使用.
They use it with another macro that returns a string with the date and time.
将 L
放在 __ DATE __
旁边会给你一个编译错误.
Putting L
next to a __ DATE __
would give you a compiling error.
Windows:对通用 Unicode 或多字节字符串使用 ##
Windows 使用类似以下内容:
Windows uses something like the following:
#ifdef _UNICODE
#define _T(x) L ## x
#else
#define _T(x) x
#endif
并且_T
在代码中随处可见
各种库,用于干净的访问器和修饰符名称:
我还看到它在代码中用于定义访问器和修饰符:
I've also seen it used in code to define accessors and modifiers:
#define MYLIB_ACCESSOR(name) (Get##name)
#define MYLIB_MODIFIER(name) (Set##name)
同样,您可以使用相同的方法创建任何其他类型的巧妙名称.
Likewise you can use this same method for any other types of clever name creation.
各种库,使用它一次进行多个变量声明:
#define CREATE_3_VARS(name) name##1, name##2, name##3
int CREATE_3_VARS(myInts);
myInts1 = 13;
myInts2 = 19;
myInts3 = 77;
这篇关于## 预处理器运算符的应用和需要考虑的问题是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!