C++中##运算符有什么作用,它被称为什么?

6

我正在查看DirectX 2009年3月SDK中附带的DXUTCore项目,并注意到他们并没有编写普通的访问器方法,而是使用宏来创建通用访问器,类似于以下代码:

#define GET_ACCESSOR( x, y )  inline x Get##y()  { DXUTLock l; return m_state.m_##y;};
...

GET_ACCESSOR( WCHAR*, WindowTitle );

看起来,##运算符只是将第二个参数中的文本插入宏中,以创建一个使用该文本操作变量的函数。这在C++中是否是标准的(即不是Microsoft特定的)?它的使用是否被认为是良好的实践?那么,这个运算符叫什么名字?

7个回答

17

6

这也是标准的C++,与Raldolpho所说的相反。

以下是相关信息:

16.3.3 ##运算符 [cpp.concat]

1 在宏定义的替换列表的开头或结尾,都不应该出现##预处理标记。

2 如果在替换列表中,一个参数紧接着前面或后面有一个##预处理标记,那么该参数将被相应的实参的预处理标记序列替换。

3 对于对象式宏和函数式宏调用,在重新检查替换列表以查找更多要替换的宏名称之前,将删除替换列表中每个##预处理标记(不来自参数),并将前面的预处理标记与后面的预处理标记连接起来。如果结果不是有效的预处理标记,则行为未定义。生成的标记可供进一步的宏替换使用。对于##运算符的求值顺序是未指定的。


5

这是一个预处理操作符,它将左右操作数连接在一起(不插入空格)。我认为它并非特定于Microsoft。


5
当然不是。C语言及其预处理器比微软早 :) - Joey
我猜也是这样,但在SO上发布你不确定的东西是很危险的,而且由于没有阅读C规范,我无法确定。 ;) - Mehrdad Afshari
然而,## 预处理器运算符并不是原始的 C 语言,虽然它很古老,但我认为它并不早于微软。 - David Thornley
1
这是标准的C语言。它的产生是因为在C预处理器的早期版本中,/**/以这种方式工作。标准规定注释必须被替换为单个空格,这样可以清理解析器中的一些边缘情况,但破坏了标记粘贴。因此,为了补偿,他们发明了标记粘贴运算符,并加入了字符串化运算符来补偿与字符串文字内部标记替换相关的另一个更改。标准的C++基本上完整地采用了C预处理器,因此可以将子集语言解析为C或C ++。 - RBerteig

3
这不是标准C++,而是标准C。请查看这篇维基百科文章
那么这样做好吗?总的来说,我讨厌预处理器宏,并认为它们和Goto一样糟糕(如果不比Goto更糟)。 编辑:显然,人们误解了我所说的“这不是标准C ++,而是标准C”的意思。许多人只读了第一个短语,而没有阅读第二个短语。我的意图是指出宏是从C中继承到C ++中的。

1
这是标准的C++,请查看我的下面的回答。 - GManNickG
1
我认为Randolpho的观点是,虽然C ++在标准中可能有该功能,但它是在C ++之前存在的,也就是说,它也是C的特性(无论是否为标准C)。 - Simeon Pilgrim
1
啊,我只是在说“这不是标准的C++”,这并不是真的。 - GManNickG
1
就像goto一样,在“正常”的编程中,goto是不好的,但是有些情况下,如果你仍然在使用C进行“正常”的编程,那么你面临的问题比goto更大。在C中,测试工具宏是一个很好的用法。 - Simeon Pilgrim
1
不,我确定他们和我一样理解了 [但我没有给你点踩]。你说了“这不是标准C ++”,这是不正确的。如果你的意思是“这是从C开始的”,我相信你不会因此受到任何负面评价,因为这是真的。此外,宏确实有其用途。它们是"邪恶的",而且通常有更好的方法来获得相同的结果,但宏仍然存在,因为在某些情况下它们是有用的。说某些东西应该“永远”不被使用,与说它们应该始终被使用一样糟糕。 - GManNickG
显示剩余3条评论

2
正如Mehrdad所说,它将操作数连接起来,例如:
#define MyMacro(A,B) A ## B
MyMacro(XYZ, 123) // Equivalent to XYZ123

请注意,MISRA C建议不要使用这个运算符(以及# “字符串化”运算符),因为其计算顺序依赖于编译器。

2

这是标准C++允许的令牌粘贴运算符(详见16.3.3)。 至于最佳实践:在我看来,使用宏不是一个好的实践(在C++中)。


1

这是宏参数的连接,即

GET_ACCESSOR (int, Age);

将被扩展到

inline int GetAge()  { DXUTLock l; return m_state.m_Age;};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接