1、预定义符号
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSIC,其值为1,否则未定义
以上这些预定义符号都是语言内置的。 直接使用就可以。
2、#define
2.1 #define定义标识符
语法: #define name stuff
下面举几个例子:
#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__)
特别提示:在define定义标识符的时候,不可以加 ;
如: #define MAX 1000; //错误的书写
2.2 #define定义宏
#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)
宏的声明方式:
#define name(parament-list) stuff
其中parament-list是由一个逗号隔开的符号表,它可能出现在stuff中。
注意:参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
栗子:#define SQUARE(x) x * x
这个宏接收一个参数x,如果在上述声明之后,如果你把 SQUARE(5); 置于程序中,预处理器就会用下面这个表达式替换上面的表达式:
5 * 5
那么问题来了————————看这个代码:
int a = 5;
printf("%d\n", SQURE(a + 1));
其实乍一看,你可能会觉得这段代码 将会打印36这个数值,事实上它将会打印 11,为什么啊?其实在替换文本时,参数x被替换成a+1,所以实际上会变成:printf("%d\n", a + 1 * a + 1); 如果要解决这个问题,只需要在宏定义上加上两个括号就可以了。
#define SQUARE(x) (x) * (x)
这样子预处理之后就产生了预期的效果:
printf("%d\n", (a + 1) * (a + 1));
问题2来了————————————
DOUBLE a = 5;
printf("%d\n", 10 * DOUBLE(a));
这个代码产生的结果也并非是我们所要的结果,替换之后会出现: printf("%d\n", 10 * (5) + (5));
由于乘法运算先于宏定义的加法,所以出现了 55,对于这个问题,解决方法是在宏定义表达式两边上加上一对括号就好了:
#define DOUBLE(x) ( (x) * (x) )
提示:所以用于数值表达式进行求值的宏定义都应该用这个方法加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。