1. 以#开头的预处理命令
预处理命令可以控制编译器在进行编译链接之前,对所写的代码进行一些其他的处理。
所谓的预处理就是在编译之前对程序的处理,所以预处理命令也叫做预编译命令。
“#”符号是预处理命令特有的符号,C语言中凡是出现“#”的地方一定是预处理命令。
编译器通过“#”号来将我们写的程序和预处理命令区分开的。
C语言的编译器,主要完成两个作用:
1)如果程序中有预处理命令,就根据预处理命令对程序做一些前期的处理,否则什么都不做。
2)对经过预处理的程序进行编译生成计算机可以识别的二进制文件。
生成可执行程序的过程如下图:
2. 预处理命令的类别
C语言提供了三类预处理命令,指导编译器来完成对程序不同层次上的修改,它们分别是:
1)宏定义
#define 被替换的内容 替换为的内容
宏定义主要分为不带参数的宏和带参数的宏:
主要来说一下带参数的宏:
#define add(x,y) x+y
在程序中,如果出现了add(...),就会发生宏替换。
带参数的宏和函数的区别:
-------处理时间不同:宏定义是在预处理阶段进行的,而函数定义是在编译阶段实现的,函数调用是在函数运行时完成的。
-------处理方法不同:宏定义是直接替换的,尽管替换有点复杂,本质上还是在进行符号替换。而函数调用是有参数传递和返回值过程的,不是简单的符号替换。
-------符号类型不同:宏定义是无数据类型的,仅仅只是符号;函数中的符号都是变量,是有类型的,如果类型不一致还会出现警告甚至错误。
注意: C语言中的宏定义只认与宏定义在一行的“替换内容”,如果想让宏定义多认几行的内容,就在每一行的后面写一个反斜杠“\”,最后一行不需要。
反斜杠的作用就是告诉编译器预处理命令还没完,后面还有。
#define add(a,b,c,rst) rst=a+b;\
rst+=c;
2)预编译控制
预编译控制可以根据条件决定那一片代码需要,哪一片代码不需要,对代码是一片一片处理的,需要的被留下,不需要的直接删掉。
预处理命令的一般形式是:
#预编译控制关键字 其他
C语言的预编译控制的关键字有以下6个:
if ifdef ifndef elif else endif
if:和if语句类似,后面的‘其他’是一个布尔表达式,如果为真,执行后面的语句块,否则不执行。
ifdef:如果定义了后面的‘其他’,‘其他’是一个标识符,如果是define命令定义的被替换的内容,执行后面的语句块,否则不执行。
ifndef:如果没有定义后面的标识符,即其他没有在define定义中出现过,则执行后面的语句块,否则不执行。
elif:类似于选择结构中的else if,如果上一个if不满足,这一个满足的话,执行后面的语句块,否则不执行。
else:类似于选择结构中的else,如果前一个if不成立,执行后面的语句块,否则不执行。
endif:一个预编译控制结束的标志,相当于是if选择结构中的最后一个右大括号。
3)头文件包含
这个预处理命令可以告诉编译器在预处理的时候,将一个文件的内容全部拷贝到另一个文件中。
放置公共代码的文件,被称为头文件,以后缀“.h”结尾的。
放置非公共代码的文件,被称为源文件,以后缀“.c”结尾的。
我们经常将一些常用的函数声明,宏定义,公共结构体类型、共用体类型和枚举类型,全局变量等公共代码都放在头文件中。
而将一些非公共的函数定义、变量定义,类型定义等放在源文件中。
一般将函数的声明放在头文件中,允许多处拷贝。而将函数的定义放在源文件中,避免函数的多处定义错误。
#include <头文件> --- 从库文件路径搜索头文件
#include ”头文件“ --- 从当前工作目录搜索头文件
C语言提供的标准头文件:
---- math.h 头文件
这个头文件提供了有关数学运算的宏,类型和函数。
如:计算一个数的平方用pow(),以2为底的对数log()等等。
---- stdio.h 头文件
提供有关输入输出的宏,类型和函数。
---- stdlib.h 头文件
提供一些辅助功能的函数,或者称之为工具。
如:讲一个字符串转换成整型数子用atoi()函数,产生一个随机数用rand()函数,内存分配malloc()函数。
---- string.h 头文件
提供字符串操作的宏、类型和函数。
字符串拼接strcat(),字符串比较strcmp(),字符串拷贝strcpy()等等。