预处理器简介
2015-06-02 16:45
204 查看
预处理器
预处理是C编译器做的第一件事情,主要是做一些文本方面的工作。包括:删除注释、插入被#include包含的文件、定义和替换由#define指令定义的符号以及代码的部份内容,和条件编译。预定义符号
预定义符号如下表所示:
__FILE__ | 进行编译的文件名 |
__LINE__ | 文件的当前行号 |
__DATE__ | 文件编译的日期 |
__TIME__ | 文件编译的时间 |
__FUNCTION__ | 函数名 |
__STDC__ | 如果遵循ANSI C,它被定义 |
#define
此指令应该是最为常见的,它的一般描述是
#define name stuff
stuff是可选的。stuff不仅可以是常量,任何文本都可以用于替换。
#define name(parameter-list) stuff
上面这种形式被称为宏macro,它作为函数的替换的方式之一被广泛采用。不过C++中不太推荐这种方法,转而使用模板。不过,宏函数还是有很特殊的地方,且模版亦不能代替。比如字符串代替。
#define PRINT(FORMAT, VALUE) \
printf("The value is "FORMAT" ", VALUE)
在宏参数两边加上引号,表示以字符串形式替换。例如,下面的语句:
PRINT("%d", x+10);
经过预编译后变为
printf("The value is %d", x+10);
这种转换只有当宏参数是字符串常量时,才可以被处理。如果在stuff里宏参数前加上'#',则对任意文本都有效。比如下面
#define PRINT(FORMAT, VALUE) \
printf("The value is "#VALUE" = "FORMAT" ", VALUE)
那么上面那条语句会编译为
printf("The value is x+10 = %d", x+10);
这样大提高了宏参数的灵活性。甚至,预处理器还有连接功能'##'(后面介绍)。
#define ADD(N, VALUE) hd##N += VALUE
…
ADD(a, 3); ó had += 3;
在许多的高级程序中,这类“奇技淫巧”被广泛使用。一方面,宏替换比函数往往能获得更高的效率;更重要的是,这类字符串处理是C/C++这种非脚本语言无法实现的。
#undef
通常是重定义一个宏。因为如果一个宏已经定义了,那么必须先取消定义,才能重新定义。
命令行定义
命令行定义就是通过编译器来定义。各种编译器都提供了一个选项来定义宏。以gcc为例:
gcc -DMAX_SIZE=100 -DLITTLE_ENDIAN
这里定义了两个,MAX_SIZE为100,LITTLE_ENDIAN没有指定值,那么默认为0.
命令行也可以取消定义,用-U。方法就不叙述了。(注意:gcc和cl都是区分大小写的)
条件编译
具体地讲,条件编译就是几个条件指令:#if, #ifdef, #elseif, #else, #endif, #ifundef, defined。比如,判断一个宏是否定义,有三种方式:
1. #if MACRO_
2. #ifdef MACRO_
3. #if defined(MACRO_)
一般情况下,用前两个就可以了。但是后一个也非常有用,比如要判断多个条件组合时
#if defined(!MACRO1 || MACRO2 && MACRO3 )
用其它方式会很麻烦。
其它指令
#error text-to-print
让编译器输出信息对开发者来说,比注释更有效。
#和##
在C语言的宏中是容许嵌套的,编译器展开宏后,会在运行以便于处理器,如果有宏,则继续,当然,如果出现递归时则会停止。一般的展开规律像函数的参数一样,先展开参数,在分析函数,所以展开顺序是由内而外,但是当宏中有#则不再展开参数了,如果宏中有##,则先展开函数,再展开里面的参数。
相关文章推荐
- [ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.3.1:
- CDH5.3.2中配置运行Spark SQL的Thrift Server
- 如何用简单易懂的例子解释隐马尔可夫模型?
- B-tree/B+tree/B*tree [转]
- 实例构造器和类型构造器
- python执行子进程实现进程间通信的方法
- jQuery中$.fn的用法示例介绍
- 数值属性的相异性:闵可夫斯基距离
- iOS 调试
- shmget函数与shmat
- 交叉编译 libde265 到arm32位库
- spring 注解 singleton prototype request session global session
- email验证
- chrome使用技巧(看了定不让你失望)
- 设计模式之 - 代理模式
- Android 小米盒子游戏手柄按键捕获 - 能获取到的 home 键依然是个痛
- 什么是LAMP?
- UVA111 LCS
- icvCreateHaarTrainingData和icvCreateBackgroundData
- 交流