C中的原始#define理解

时间:2011-07-04 10:34:45

标签: c++ c

我在C中定义了一个像这样的宏:

  #define SOME_FIELD(_A_,_B_,_C_) \
    MyObj[ ## _A_ ## ].somePTR =        \
    (DWORD_PTR) (buff_ ## _C_  ## _C_ ## _ ## _B_ ## );

我能理解的是,对于索引 A ,我们获得了“somePTR”的一些价值。我的问题是,什么是## <name> ##表示法,以及如何计算somePTR的值?

我是这样一个宏的新手,所以描述性的解释会非常有用。

4 个答案:

答案 0 :(得分:7)

这称为token concatenation。它允许您将参数粘合在一起。

对于您的示例,SOME_FIELD(Param1,Param2,Param3);扩展如下:

MyObj[Param1].somePTR = (DWORD_PTR) (buff_Param3Param3_Param2);

使用编译器的预处理器自己尝试这一点很容易。您通常不需要编写完全成熟的C程序 - 预处理器通常可以自行调用。

答案 1 :(得分:1)

这是预处理器令牌粘贴

http://msdn.microsoft.com/en-us/library/09dwwt6y(v=vs.80).aspx

它会将实际参数标记复制为字符串文字,因此请将其读取为

 // preprocessor_token_pasting.cpp
#include <stdio.h>
#define paster( n ) printf_s( "token" #n " = %d", token##n )
int token9 = 9;

int main()
{
   paster(9);
}

答案 2 :(得分:1)

##是concatenation原语,它用于创建符号。

在宏中创建名称很有用:

#define GENERIC_GETTER(f,g) (g->member_ ## f )

GENERIC_GETTER(a,b)将创建(b->member_a)(已创建新符号)。如果你不使用尖锐的,它会创建(b->member_ a)(没有粘在一起)

答案 3 :(得分:1)

通常,##运算符会连接两个令牌:它需要合法的 左边是令牌,右边是合法令牌,结果是新的 令牌。在你的情况下,宏中的第一行 (MyObj[&nbsp;##&nbsp;_A_&nbsp;##&nbsp;].somePtr&nbsp;=&nbsp;\)是 非法,并导致未定义的行为。大多数实现只是 连接字符串,然后在完成所有字符串后重新声明 替换,所以它会工作,但它不能保证。到目前为止 我在这里可以说,没有必要。在第二行,在 另一方面,您正在生成新令牌。如果你调用宏:

SOME_FIELD(x,y,z);

它将扩展为:

MyObj[x].somePtr = (DWORD_PTR)(buff_zzy);

(我可能会补充说,_A__B__C_等符号的使用也是 未定义的行为。以下划线开头的符号 大写字母位于实现的名称空间中。)