我正在尝试执行以下代码:
#define channel1 10
#define channel(id) channel##id
int main(){
int id = 1;
cout << channel(id)<<"\n";
return 0;
}
我收到以下错误:
错误:使用未声明的标识符“channelid”
相反,我希望输出为 10,因为应该将 channel(id)
预处理为 channel1
并将值替换为10.
有什么方法可以实现吗?
最佳答案
问题是因为您试图混合在代码处理的不同阶段考虑的信息。
宏和所有 CPP (C-Pre-Processor) 的东西在其他任何事情之前发生(正如它自己的名字所示)。它对变量值一无所知(最多是关于#define),而且它所做的大部分工作都是文本处理。
一些变量值可能在编译时已知(参见 constexpr
)...但其中大部分只有在运行时才知道。
因此,总而言之,您的代码失败了,因为预处理器对 id
变量一无所知。
编辑:解释 sum 示例。
我们有这个代码x.cpp
#define sum(a,b) a + b
int main(int argc, char **argv) {
int x = 1, y = 2;
return sum(x,y);
}
并且这段代码可以编译并且运行良好。
让我们看看幕后发生了什么。
所有 C/C++ 源文件都经过预处理。这意味着它们使用与 C 或 C++ 不同的语言进行评估:CPP(C 预处理器)。这个 CPP 负责所有 #... 内容(例如搜索和包含头文件),正如我所说,与 C 或 C++ 无关。
事实上,你甚至可以在没有编译器的情况下运行它(尝试cpp x.cpp
)或者你可以指示编译器只执行这个阶段(g++ -o x.i -E x .cpp
)
如果我们查看 x.i:
# 1 "x.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "x.cpp"
int main(int argc, char **argv) {
int x = 1, y = 2;
return x + y;
}
我们可以观察到几件事:
- 还有许多额外的“#”行。编译器使用这些来跟踪所有内容的来源以及所包含位的来源,以便能够提供有意义的错误消息。
- 请注意我们的 sum 宏是如何在代码中被替换的。这是盲目完成的,结果字符串被证明是不正确的 C/C++ 语法,它不会被检测到,但只有在实际的 C/C++ 解析完成时才会被检测到。
关于c++ - 如何在传递给 C/C++ 宏之前解析 int 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54972468/