第十四章
- 指令的规则
- 指令都以
#
开始 - 在指令的符号之间可以插入任意数量的空格或水平制表符
- 指令总是在第一个换行符处结束,除非明确的指明要延续
- 指令可以出现在程序中的任意地方
- 注释可以和指令放在同一行
- 指令都以
- 使用带参数宏替代函数的优缺点
- 程序可能会稍微快些,程序调用函数会有些额外的开销——存储上下文信息,复制参数值等(C99的内联函数提供了另一种避免这种开销办法)
- 宏更“通用”:可以接受任意类型的参数
- 编译后的代码通常会变大
- 宏参数没有类型检查
- 无法使用一个指针指向一个宏
- 宏可能不止一次的计算参数
-
#
运算符:将宏的一个参数转换为字符串字面量#define PRINT_INT(X) printf(#x " =%d\n",x)
-
##
运算符:将两个记号(如标识符)“粘合”在一起,成为一个记号。- 用的地方不是很多,可用于生成标识符,或者函数
- 宏的通用属性
- 宏的替换列表可以包含对其它宏的调用
- 预处理器只会替换完整地记号,不会替换记号的片段
- 宏定义的作用范围通常到出现这个宏的文件末尾
- 宏不可以被定义两遍,除非新的定义与旧的定义是一样的
- 宏可以使用
#undef
指令“取消定义”
- 空的宏参数
- C99允许宏调用中的任意或所有参数为空。当然这样的调用需要和一般调用有一样多的逗号。
- 当空参数是
#
运算符的操作数,空的实际参数被#
运算符“字符串化”,则结果为""(空字符串) - 当空参数是
##
运算符的操作数,空的实际参数会被不可见的“位置标记”记号代替。把原始的记号与位置标记记号相连接,得到的还是原来的记号(位置标记记号消失了),如果连接两个位置标记记号,得到的是一个位置标记记号。宏扩展完成后,位置记号标记从程序中消失。
- 参数个数可变的宏
- C89中,如果宏有参数,那么个数是固定的。C99中可变,例:
#define TEST(...) printf(__VA_ARGS__)
- C89中,如果宏有参数,那么个数是固定的。C99中可变,例:
-
__func__
标识符-
跟踪函数调用
#define FUNCTION_CALLED() printf("%s called\n", __func__) #define FUNCTION_RETURNS() printf("%s returns\n", __func__)
void f(){ FUNCTION_CALLED() ; ... FUNCTION_RETURNS(); }
作为参数传递给函数,让函数知道调用他的函数的名字
-
-
#line
指令用法:#line n
,#line n "文件"