C和指针-8


预处理器

预定义符号

符号 示例 含义
__FILE__ "a.c" 进行编译的源文件名
__LINE__ 5 文件当前的行号
__DATE__ "Jan 1 1999" 文件被编译的日期
__TIME__ "18.11.22" 文件被编译的时间
__STDC__ 1 是否遵循 ANSI C

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)

#define name(parameter-list) stuff

其中, parameter-list 参数列表是一个逗号分隔的符号列表,它们可能出现在 stuff 中。参数列表的左括号必须与 name 紧邻。如果有空白,则被解释为 stuff 的一部分。

例如:

#define SQUARE(x) ((x) * (x))

用于对数值求值的宏定义都应该使用这种方式加上括号,避免在使用宏时,由于参数中的操作符或邻近的操作符之间不可预料的相互作用。

#define 替换

在程序中扩展#define 定义符号和宏时:

  • 首先对参数进行检查,看看是否包含了任何由#define 定义的符号,如果是,它们首先被替换。

  • 替换文本被插入程序中原来文本的位置,对于宏,参数名被它们的值所替代。

  • 最后,再次对结果文本进行扫描,检查是否包含了任何由 #define 定义的符号,如果是,就重复上述处理过程。

这样,宏参数和#define 定义可以包含其它#define 定义的符号,但是宏不可以出现递归。

当预处理器搜索#define 定义的符号时,字符串常量的内容不进行检查。如果想把宏参数插入到字符串常量中,可以使用预处理器把一个宏参数转换成一个字符串。

#argument 这种结构被预处理器翻译为 "argument"

#define PRINT(FORMAT,VALUE)    \
        printf("The value of " #VALUE \
        " is " FORMAT "\n", VALUE)
...

PRINT("%d", x+3);

//输出
The value of x+3 is 25

## 把位于它两边的符号连接成一个符号

#define ADD_TO_SUM(sum_number, value)   \
        sum ## sum_number += value
...
ADD_TO_SUM(5, 25);

最后一条语句把值25加到sum5,注意这种连接必须产生一个合法的标识符

宏与函数

宏经常用于简单的计算,效率比函数要高,函数的参数必须声明为一种特定的类型,宏与类型无关。

无法使用函数实现:

#define MALLOC(n,type)\
        ((type *)malloc((n) * sizeof(type)))

宏的副作用

参数为x++类型时,可能自加多次。同样的,以函数返回值作为参数,函数可能执行多次。

命名约定

  • 把宏名字全部大写

#undef

用于移除一个宏定义

命令行定义

UNIX编译器中使用-D选项可以完成命令行定义。例如

cc -DARRAY_SIZE=100 prog.c

UNIX编译器中使用-U选项可以忽略符号的初始定义。

条件编译

#if constant-expression
        statements
#elif constant-expression
        onther statements
#else 
        onther statements
#endif

文件包含

库文件包含 #include <filename.h>
本地文件包含 #include "filename.h"

  • 分享:
评论
还没有评论
    发表评论 说点什么