携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情
宏、枚举和常量(下)
宏
C++里面的宏,还可以实现类似函数的功能,但是要注意的是,由于宏做的是纯文本替换,所以对于下面这个例子,可能无法达到开发者本来想要达成的效果:
#define X 5
#define Y X+5
#define Z Y/5+1
这里Z的值,预期应该是,但实际上却是,这种错误就在于没有认识到#define生效的阶段。这里可能要多引入一点C++编译过程的解释。
一段C++代码编译的过程可以被细分为这样几步:
- 预处理,对应到g++里面就是
-E选项,这一步的产出就是.i文件,这个文件其实还是文本文件,只不过会将预编译指令进行展开,比如本文中讲到的#define以及包含头文件用的#include等。 - 汇编,对应到g++里面就是
-S选项,这一步的产出就是.s文件,即C++高层语言对应的低级语言即汇编语言代码,文本文件类型,其实基本就是1:1的翻译,当然也可能编译器会根据优化级别对指令进行相应的优化,这部分内容不在本文讨论范围之内。 - 单个文件编译,对应到g++里面就是
-c选项,这一步的产出就是.o文件,是人类不可读的二进制文件了,每一个.c、.cpp文件都对应一个.o文件。 - 将静态库和.o文件一起进行静态编译,这里使用的是
ld软件。
所以其实#define发生在词法、句法分析之前,这也就是为什么宏无法理解运算符优先级的原因了。
宏其实还有一种用法,就是用来拼接变量的名称,具体用法见如下代码:
#include <cstdio>
#define FUNC1(a) #a
#define FUNC2(a,b) a##b
int main() {
int hello = 1, world = 2, helloworld = 3;
printf(FUNC1(hello)FUNC1(world)"=%d",FUNC2(hello,world));
return 0;
}
输出就是:
helloworld=3