目录
前言:
预处理指令 都是在 程序 的预处理阶段 执行完毕,在 .i 后缀预处理文件 中 可以发现预处理指令的处理结果
正文开始
1. 预定义符号
C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为 1 ,否则未定义:如在VS编译器中使用 会报错:说明 VS不遵循ANSI C标准
举个例子:
printf("file:%s line:%d\n", __FILE__, __LINE__);
2. #define定义常量
基本语法:
#define name stuff
举个例子:
1、 定义 数值
#define MAX 1000
2、为关键字重命名:为 register这个关键字,创建一个简短的名字
#define reg register
3、 代替 一段代码直接 : define定义一个 符号 代替 一段代码
#define DEBUG_PRINT printf(" file:%s\n line:%d\n date:%s\n time:%s\n" ,__FILE__,__LINE__ , __DATE__,__TIME__ )
4、(代码若过长可以使用 续行符: 一个 斜杠 + 换行本质是将 换行符“\n”变成 “\\n” 使换行符失效,不再换行,则代码就判定为同一行)
#define DEBUG_PRINT printf(" file:%s\n \
line:%d\n date:%s\n time:%s\n" ,\
__FILE__,__LINE__ , \
__DATE__,__TIME__ )
思考:在定义定义标识符的时候,要不要在最后加上 分号: ; ? 比如:
#define MAX 1000;
#define MAX 1000
建议不要加上 ; ,这样容易导致问题。 比如下面的场景:
if (condition)
max = MAX; (替换后 max = 1000;; 一个分逗号 算做一个语句)
else
max = 0;
如果是加了分号的情况,等替换后,if 和 else 之间就是 2 条语句,而没有大括号的时候,if后边只能有一条语句。这里会出现语法错误。
3. #define定义宏
#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。 下面是宏的申明方式:
#define name( parament-list ) stuff
其中的 parament - list 是一个由逗号隔开的符号表,它们可能出现在stuff中。 注意: 参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
举例:
1 #define SQUARE( x ) x * x
这个宏接收一个参数x.如果在上述声明之后,你把SQUARE( 5 );
置于程序中,预处理器就会用 下面这个表达式替换上面的表达式:5 * 5
#include<stdio.h>
#define SQUARE(x) x*x
int main()
{
int a = 5;
printf("%d\n", Square(a)); // 在预处理后的 程序中 这一句话变成 printf("%d\n", a * a);
return 0;
}
警告: 这个宏存在一个问题: 观察下面的代码段:
int a = 5;
printf("%d\n" ,SQUARE( 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) );
这里还有一个宏定义:
#define DOUBLE(x) (x) + (x)
定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。
int a = 5;
printf(" %d\n" , 10 * DOUBLE(a));
这将打印什么值呢?看上去,好像打印 100 ,但事实上打印的是55. 我们发现替换之后:
printf ( "%d\n",10 * (5) + (5));
乘法运算先于宏定义的加法,所以出现了 55 .(因为本质 就是直接 替换,直观上的那种的套壳)
这个问题,的解决办法是在宏定义表达式两边加上一对括号就可以了。
#define DOUBLE(x) (( x ) + ( x ))