请检查我的示例代码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。
你能告诉我我犯了什么错误以及如何绕过这个错误吗?
答案 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)