预处理是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、#include''stdio.h''两种表示形式有区别,第一种,系统会直接在C库函数头文件所在的目录中查找要包含的文件,第二种是在用户当前目录中查找,如果找不到才回到C库函数头文件所在的目录中查找要包含的文件,当然双引号中也可以指定文件所在的路径。
常用在文件头部被包含的文件成为标题文件或者头部文件,一般以.h为后缀。
常把宏定义、结构、联合、枚举声明、全局变量声明、外部函数声明等放到.h的文件中。
小编推荐一个学C语言/C++的学习裙【 六六六,二九五,四九八 】邀请码凌云,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!
三、条件编译:
一般的情况下,源程序中所有的代码都会参加编译,但有时我们希望对一部分内容在满足一定条件下才会进行编译,这个时候条件编译就产生了作用。
、#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
};
小编推荐一个学C语言/C++的学习裙【 六六六,二九五,四九八 】邀请码凌云,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!
上面的代码你会发现,编译通过并没有报错,之间根本就是乱写的,居然还能通过,那是因为中间语句不被编译,所以能通过,如果换成if那么就会报错。
、#ifdef跟#ifndef指令:
这两个用于判断一个宏替换是否被定义,#ifdef用于如果被定义则编译后面的语句块,#ifndef用于如果没有定义则编译后面的语句块,其一般形式为:
#ifdef 宏替换名
语句块;
#endif
#ifndef 宏替换名
语句块;
#endif
当然了,也可以跟#else,一般形式为:
#ifdef(#ifndef) 宏替换名
语句块;
#else
语句块;
#endif
、#undef命令:
其一般形式为:#undef 宏替换名,用于提前终止宏替换名的作用范围,上面讲解过。
、#line命令:
#line一般形式如下:#line 行号[文件名]。
其中行号为任意正数,_LINE_用于存放当前正在编译的行数,_FILE_存放当前编译的文件名。如要得到当前行数:printf(''%d'',_LINE_);。