并非所有宏都被替换掉了吗?

时间:2016-11-15 08:56:36

标签: c++ macros

请检查我的示例代码http://ideone.com/6xS1xg。该代码的目的是以简约的方式显示问题。

#include <iostream>
using namespace std;

#define myNode NodeP
#define f(x) fp(x##NodeStr)

int fp(void *  x)
{
    return 0 ;
}

int main() {

    void *  NodePNodeStr = NULL;
    f( myNode);

    return 0;
}

上面代码的目的是让我怀疑为什么宏替换在这里没有用。 myNode似乎没有被NodeP取代。我在编译中得到的错误是prog.cpp:14:5: error: 'myNodeNodeStr' was not declared in this scope f( myNode);。但是,不应该搜索myNodeNodeStr,但它应该搜索NodePNodeStr。

你能告诉我我犯了什么错误以及如何绕过这个错误吗?

2 个答案:

答案 0 :(得分:4)

如果您打算将宏传递给宏,则必须考虑到需要额外的宏扩展,因为它最初不会作为参数扩展。

#include <iostream>
using namespace std;

#define myNode NodeP
#define fp_(x) fp(x##NodeStr)
#define f(x) fp_(x)

int fp(void *  x)
{
    return 0 ;
}

int main() {

    void *  NodePNodeStr = NULL;
    f( myNode);

    return 0;
}

因此,要展开f,预处理器会将其myNode传递给fp_(myNode)。只有现在预处理器才会扩展所有此表达式中的宏。

就像这样,因为预处理器的主要用途是令牌生成(通过字符串化和连接运算符,###)。因此传递给宏的任何东西都不能在涉及这些运算符时立即扩展。

答案 1 :(得分:2)

##运算符从字面上理解宏参数,因此myNode不会扩展为NodeP,结果为myNodeNodeStr

当宏替换变深时,裸##通常不是你想要的。封装它会更好。参数传递的额外步骤会导致预期的扩展。

#define CAT_LIT( A, B ) A ## B // Catenate literal tokens.
#define CAT( A, B ) CAT_LIT( A, B ) // Catenate fully-expanded parameters.

然后这将正常工作:

#define f(x) CAT(x, NodeStr)