·预定义符号介绍·预处理指令 #define·宏和函数的对比·预处理操作符#和##的介绍·命令定义·预处理指令 #include·预处理指令 #undef·条件编译
1、预处理详解
1.1预定义符号
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
1.2#define 的认识
语法:
#define name stuff
定义:
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏( macro )或定义宏(define macro )。
#define MAX 1000
#define reg register //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )
1.2.1 #define 使用的时候的注意点
define DOUBLE(x) x + x
int a = 5;
printf("%d\n" ,10 * DOUBLE(a));
那上面的代码的答案是多少呢?100?50?
所以在使用#define的时候一定要多小心不让很容易出错误的。这题的答案为50,程序会直接把5+5带入进去,就会变成 10*5+5 ,所以在用它的时候一定要加括号避免出现这样子的误。
#define DOUBLE( x) ( ( x ) + ( x ) ) //这样子就比较好的啦!!!
1.2.2#define的替换规则
在程序中扩展 #define 定义符号和宏时,需要涉及几个步骤。1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先 被替换。2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是就重复上述处理过程。注意点:1. 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归。2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
1.2.3是否带来副作用
- #define 宏 参数的求值需要给参数加上相应的括号
- 否则邻近操作符可能会影响所求值的结果,这是因为宏只是做了简单的替换操作
- 即使加上括号,带有副作用的宏参数 可能也会使得计算结果出错
- 函数的参数只在函数调用时求值一次,并将结果传递给函数即可
1.2.4 #和##
#define PRINT(FORMAT, VALUE)\
printf("the value is "FORMAT"\n", VALUE);
PRINT("%d", 10);
#define PRINT(FORMAT, VALUE)\
printf("the #value is "FORMAT"\n", VALUE);...
PRINT("%d", 10);
而第一个答案为:the value of value is 10
而第二个答案为:the 10 of value is 10
这个就是#的魅力之处了,像上面代码中#VALUE 就直接把i带入进去这个就是要注意的地方
##
可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。
#define ADD_TO_SUM(num, value)
sum##num += value;
...
ADD_TO_SUM(5, 10);//作用是:给sum5增加10.
1.2.5宏和函数的区别
命名规定:
把宏名全部大写函数名不要全部大写