1

我知道 C++ 文件开头的定义是预处理器指令,因此“预处理器在代码的实际编译开始之前执行,因此预处理器在语句 [1] 生成任何代码之前消化所有这些指令”。

现在,如果我有这个简单的例子怎么办:

#define PRINT(function) printFnctionName(#function)

void printFnctionName(string name)
{
    cout << name;
}

void test(){};
int main(int argc, char *argv[])
{
    PRINT(test);
}

所以现在我的问题实际上是预编译器如何知道将传入什么函数?预编译/链接/编译是如何真正发生的?

另外,我使用define而不是常规函数的原因是因为我无法找到复制此功能的方法`#function来检索函数的名称

4

3 回答 3

2

所以现在我的问题实际上是预编译器如何知道将传入什么函数?预编译/链接/编译是如何真正发生的?

预处理器什么都不知道。它只是用定义的值替换文本并将您传入的值字符串化。

所以编译器看到它:

void printFnctionName(string name)
{
    cout << name;
}

void test(){};
int main(int argc, char *argv[])
{
    printFnctionName("test");
}
于 2013-01-19T23:31:50.180 回答
1

预处理器进行文本替换。在您的情况下,您的代码将转换为:

int main(int argc, char *argv[])
{
    printFnctionName("test");
}

在编译过程的其余部分开始之前由预处理器执行。一些预处理器指令很简单,而另一些则复杂得多(例如,可变参数预处理器指令)。

当然,它要求您包含正确的头文件等。

于 2013-01-19T23:30:02.200 回答
0

对于这种特殊情况,答案有两个部分。一方面是 C 预处理器对正在调用的函数一无所知,它只是进行文本替换。

第二部分是“字符串化器”,#function实际上替换testPRINTwith的输入"test"。当然,它不一定是一个函数——仅仅因为它被称为 printfunction,你可以这样做:

 PRINT(a+b);

你会得到代码:

 printFnctionName("a+b");   

或者

 PRINT(a-*&1,78^%j)

并得到:

 printFnctionName("a-*&1,78^%j");   

[为什么u缺少 printFnctionName?]

如果您有类似的东西,字符串化运算符非常有用

#define ASSERT(x) do { if (!x) fail_assert(#x, __FILE__, __LINE__); } while(0)

void fail_assert(const char *expr, const char *file, int line)
{
     cerr << "Assertion (" << expr << ") failed at " << file << ":" << line << endl;
}

.... 

ASSERT(ptr != NULL);

现在您会收到一条错误消息“断言失败 (ptr!= NULL) at myprog.cpp:112”,这可能非常有用。

于 2013-01-19T23:45:36.447 回答