程序预处理 -- 宏定义

大部分入门教材都很少提到预处理,在此给大家分享一下预处理各指示字的应用。

我们知道,源代码要编译成可执行文件,首先就必须经过预处理。而预处理就是把源文件中的指示字进行处理。而指示字(directive)一般放在程序开头,并以#为开头的代码。当然,指示字也可以出现在程序的任何地方。

来看看指示字之一的#define  :宏定义

所谓宏定义,说白了就是把一个表达式或常量定义成一个符号,这个符号可以带有参数。程序在预处理的时候就把这个符号用等价的代码替换。当然

举个例子:

第13行定义100为A,类似于const的使用,不过两者有本质的区别。

第14行定义showint(a)为一个printf的函数,并带有参数a。

可以看看预处理后的结果:

头文件被展开,宏定义也被展开。

同时也可以看到,宏定义在预处理时就被处理掉了。而const要等到汇编之后才能处理,也就是说,处理的优先级是先处理宏定义。

下面在看看:

(\反斜杠可用来分割代码,方便阅读)

输出结果是:

并没有输出ocean;

这说明宏定义在字符串中是不被处理的。当然,如果把上面例子用“”号隔开ARGTERM,就可以传递参数,打印出ocean了。当然,也可以在 参数前 加#号把宏定义字符串化(即把参数换成#ARGTERM)。

另外,用宏定义来定义函数时,既要注意效率的问题,也要注意优先级的问题,后者可能会带来重大错误;

例如:

#define max(A,B) (A>B?A:B)
//这样写对吗?
//错误1:没有考虑到优先级;假如有如下一段代码:
max((a+b),(c+d));//预处理后会怎么样呢?
不难得知:结果为
a+b>c+d?a+b:c+d;
结合优先级的问题,结果不难知道

再者,并且,参数将会运算两次,这代表着什么?

1、运算效率的不成熟,凭空多了1次运算;

2、如果上面的参数是a++,b++呢?那就更加糟糕了;

尽管如此,宏定义还是非常有价值的。例如,<ctype.h>头文件中定义的函数也是常常通过宏实现的;(引用K&R的《C程序设计》)


宏(macro)既可以是静态的,也可以是动态可变的。即宏的参数可以是可变个。下面才是重磅

宏定义如#define P(...) printf(__VA_ARGS__)可以输入多个参数;

这里要注意__VA_ARGS__两边是用双下划线。

预处理后的结果是:

处理成功;

 

综上:

宏定义是可带参数的,可以是固定个,也可以是可变个。可变个时用 ... 来代替,并储存在__VA_ARGS__之中

宏定义:可以是个常量

            也可以是个带参数的表达式

            也可以是个带可变参数的表达式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章