预处理是C语言特有的功能,如:宏定义、条件编译等等,好处嘛,很多,如程序可读性好、便于修改以及移植与调试等,好处这么多,那我们今天就介绍一下。 一、宏定义: 宏定义指令使用:#define,它用来定义一个可替换的宏,分为不带参数的宏定义跟不带参数的宏定义,我们一个一个介绍。 ①、不带参数宏定义: 首先看不带参数的宏定义一般形式: #define 宏名 字符串 说明:加上#符就代表这是一条预处理指令。 宏名当然就是一个标识符。 字符串这里可以是常量、格式字符串,当然也可以是表达式。 如:#define PI 3.14,其作用就是在编译预处理时,只要在程序中遇到PI,那么就直接用3.14代替。用此有一个好处,就是想要改变程序中PI的值时,只需要直接改变预处理语句后面PI的值,那么整个程序PI的值就会改变。 还有一点就是,宏名要大写,以区别其他变量。 当然了,当一个宏名定以后也可以成为其他宏名定义的一部分,如#define r 2,#define C 2*PI*r。 宏替换不仅可以代替一般字符串,更可以替换关键字,如#define P printf,此语句用P替换关键字printf。如printf('i love you!'),可以换为P('i love you!'),这两句是等效的。 注意:如果在字符串中包含宏名,那么是不会进行替换的。如#define TEXT 'love',char *pc='i TEXT you!';printf('%s',pc)。最后输出不会是i love you!,而是输出i TEXT you!。 还有一点需要注意的是,不能将宏定义分散到程序当中,必须将其放到开始处或独立文件中,这样的有效范围为从定义处到源文件结束。但是有时我们并不需要有效范围到源文件末尾,因此,我们就可以使用#undef指令来提前结束有效范围,如printf(TEXT);#undef TEXT;后面的语句就不能再用TEXT了。 还有宏定义只是用于预处理命令,它只做字符替换,不会分配内存空间,这一点跟变量有所不同。 ②、带参数的宏定义: 带参数的宏定义一般形式如下:#define 宏名(参数列表) 字符串,当然了,还是举一个例子吧: #define M(a,b) ((a)*(b)) printf('%d',M(3,4)); 结果为12,从结果可以看出,带参数的宏定义不仅仅是字符串替换还要进行参数替换。 注意:上面看到给参数加上括号并且还在整个表达式外都加上了括号,为什么这样呢?其实举一个简单例子,如果不在参数外加括号,如#define M(a,b) (a*b) 如果这样printf('%d',M(3,3+4));那么结果是什么呢?结果是3*3+4=13,而我们想要的结果为21,所以最好把参数用括号括起来。 还有为啥还要加外括号呢?其实在举一个例子,如#define M(a,b) (a)+(b);printf('%d',2*M(3,4)),结果为2*3+4=10,但是这并不是我们想要的结果14,所以要加上外括号。 还有在宏定义中,形参并不分配内存空间,因此不需要指定类型。 还有宏名跟参数列表括号之间不能用空格,因为宏定义将会把宏名空格以后的字符都作为替代字符串的一部分。 二、#include指令: 此指令的作用是:将另一源文件的全部内容都包含都本文件当中,有两种表示形式#include 常用在文件头部被包含的文件成为标题文件或者头部文件,一般以.h为后缀。 常把宏定义、结构、联合、枚举声明、全局变量声明、外部函数声明等放到.h的文件中。 三、条件编译: 一般的情况下,源程序中所有的代码都会参加编译,但有时我们希望对一部分内容在满足一定条件下才会进行编译,这个时候条件编译就产生了作用。 ①、#if命令: 一般形式为: #if 常量表达式 语句块 #endif 如果为真那么后面的程序段将会被编译,如果为假,则跳过不编译。 当然了,还有#else作用为#if的另一种选择,跟else想近。 前面有个条件语句else if。当然条件编译语句也有类似的#elif,一般形式为: #if 表达式1 语句块; #elif 表达式2 语句块; …… #elif 表达式n 语句块; #endif 当然你可能不太理解,用条件语句不是也可以实现吗?也许你不理解编译的概念,条件语句中的什么if else if不管后面表达式真假,都会被编译,只是在执行过程中选择执行或不执行,举一个简单例子: #include int main(){ int a=10; #if a>10 ashduehejfj; #endif }; 上面的代码你会发现,编译通过并没有报错,之间根本就是乱写的,居然还能通过,那是因为中间语句不被编译,所以能通过,如果换成if那么就会报错。 ②、#ifdef跟#ifndef指令: 这两个用于判断一个宏替换是否被定义,#ifdef用于如果被定义则编译后面的语句块,#ifndef用于如果没有定义则编译后面的语句块,其一般形式为: #ifdef 宏替换名 语句块; #endif #ifndef 宏替换名 语句块; #endif 当然了,也可以跟#else,一般形式为: #ifdef(#ifndef) 宏替换名 语句块; #else 语句块; #endif ③、#undef命令: 其一般形式为:#undef 宏替换名,用于提前终止宏替换名的作用范围,上面讲解过。 ④、#line命令: #line一般形式如下:#line 行号[文件名]。 其中行号为任意正数,_LINE_用于存放当前正在编译的行数,_FILE_存放当前编译的文件名。如要得到当前行数:printf('%d',_LINE_);。 上面就是检验介绍一些预处理的基本知识。希望对你们有用。 |
|