您的位置:首页 > 其它

预处理器简介

2015-06-02 16:45 204 查看


预处理器

预处理是C编译器做的第一件事情,主要是做一些文本方面的工作。包括:删除注释、插入被#include包含的文件、定义和替换由#define指令定义的符号以及代码的部份内容,和条件编译。

预定义符号

预定义符号如下表所示:
__FILE__
进行编译的文件名

__LINE__
文件的当前行号

__DATE__
文件编译的日期

__TIME__
文件编译的时间

__FUNCTION__
函数名

__STDC__
如果遵循ANSI C,它被定义

预定义符号都是双下划线,通常用到最多的是前2个,用于打印log.

#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语言的宏中是容许嵌套的,编译器展开宏后,会在运行以便于处理器,如果有宏,则继续,当然,如果出现递归时则会停止。一般的展开规律像函数的参数一样,先展开参数,在分析函数,所以展开顺序是由内而外,但是当宏中有#则不再展开参数了,如果宏中有##,则先展开函数,再展开里面的参数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: