#define的简单使用
语法:
#define name stuff
对于#define的基本语法理解起来其实并不困难,
无非就是把name替换成stuff罢了。
但是,在这里,依然有一些需要我们注意的点。
首先,我们长期编写程序,都已经习惯了在语句后面加上;
其实,#define的后面是不需要加 ; 的。
我们可以看到,#define是不需要分号的,这样,我们可以很好的编译并且通过我们的程序。
#define的原理
那#define到底是怎么一回事呢?
我们首先要知道,要产生一个可执行文件,我们的程序要经过以下几个阶段
预处理》》编译》》汇编》》链接
而#define就是在预处理阶段所进行的一系列操作。
如果我们想要观察其原理,首先要进行一些列操作
首先进入项目属性
把预处理到文件变成 是
然后我们就可以从项目目录中打开后缀为i的文件
打开之后,我们就可以很好的观察!
我们可以看到红色方框中,MAX已经被替换为了100
这一万多行代码,就是编译器对程序进行的预处理
#define定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
这是定义宏的定义,或者说是一种规矩
下面则是#define的声明方式
#define name( parament-list ) stuff
其中,paramen-list是一个用逗号隔开的符号表,
你可以把它理解为函数中参数的形式。
但要谨记,name和(parament-list)之间必须紧密相连!
如果出现了空格,那么,(patament-list)就会被认为是stuff的一部分!
这样就出现了bug
那么具体怎么使用呢?我来为大家举一个简单的例子
我们可以看到,我定义了一个宏,这个宏里面有两个参数,x和y
然后进行相加
实际上#define就是把main函数中的add(a,b)替换成了a+b
哈,就这么简单
我们再来看一个例子
这次,我们把add改成了x乘y的功能
然后让a+b与b相乘
但是,为什么结果是5而不是6呢?
让我们再来观察下预编译文件
原来是酱紫!#define只负责把文本替换过去,但是符号与符号之间存在着优先级!这样以来,就造成了bug,本来是想让a+b乘以b,现在却成了,a加上b的平方
那么,宏定义变量中就不能有表达式吗?
其实啊,我们还有一个非常无敌的符号,就是小括号!
在小括号内,自然是优先运行的!
那么我们只需要对程序进行以下修改
#define add(x,y) ((x)*(y))
用小括号将其包裹
此时,我们再来观察预处理文件
这样以来,就能很好的实现相乘的功能了!
所以我们要记住
在定义宏中,不要吝啬你的括号!!!
#define的替换规则
首先,固然宏有参数,但是并不具备递归的功能。
在程序中扩展#define定义符号和宏时,需要涉及以下步骤
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。
- 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
- 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
- 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。(也就是说,在字符串内不搜索)
举个栗子!
这里,我们把AA BB 分别替换为1 2,然后把AA BB作为‘参数’,
那么编译器在预处理的时候就会先把1 2替换进去,然后再将add替换进去,
预处理后,代码实际上就成为了图片右边的形式。
#和##
如何将参数插入到字符中呢?
我们发现,字符串有自动链接的特点,哪怕是多个双引号,也能一并打印
#的作用
#char可以替换为“char”也就是一个字符串
这就是#的应用
还有##,##的作用是
##可以把位于它两边的符号合成一个符号。
它允许宏定义从分离的文本片段创建标识符。
从图中,我们可以看出,##把a和num连接到了一起,也就把add(num)替换成了,a1以及a2
文章评论