预处理指令:在程序编译前执行,效率高,以符号#开头,没有';'结尾的编译指令,这些指令称为预处理命令,预处理命令属于C语言编译器,而不是C语言的组成部分,通过预处理命令可扩展C语言程序设计的环境,
例:
#include<stdio.h> #include“stu.h” #include <string.h> |
系统文件用<>,自己写的用””
宏定义 |
文件包含 |
条件编译 |
定义常量 |
|
|
宏定义不仅在编译前执行,效率比较高,并且不会检测内存,如果替换之后会发生检测
#include<stdio.h> #include"stu.h" #include<string.h> #define LENGTH 20 //length叫宏名,20为被宏名替换的字符串 int main(int argc,const char * argv[]) { for (int i=0; i<LENGTH; i++) { printf("%i\n",i); } return0; } |
在编译之前会检查所有的LENGTH并把它替换为20
带参数的宏定义注意点,宏定义的参数只做替换操作并不会做计算操作
#include<stdio.h> #include"stu.h" #include<string.h> #define calcSum(a,b) a*b int main(int argc,const char * argv[]) { int i=calcSum(2+2,3+6); 替换过程 // calcSum(a,b) a*b // int i=a+b; int i=2+2*3+6 return0; } |
所以宏定义的计算过程定义应该用括号就要采取以下定义方式
#include<stdio.h> #include"stu.h" #include<string.h> #define calcSum(a,b) (a)*(b) int main(int argc,const char * argv[]) { int i=calcSum(2+2,3+6); 替换过程 // calcSum(a,b) a*b // int i=a+b; int i=2+2*3+6 int k=calcSum(2+2,3)/calcSum(1,2); //int k=2+2*3/1*2 return0; } |
但是这种定义方式还是不完美存在某些bug,所以我们应该把计算结果也用括号包住,总之我们要记住因为它只是很笨拙的做了替换操作,所以我们在使用宏定义的时候要特别小心
#define calcSum(a,b) ((a)*(b)) //最终正确定义 |
条件编译由宏定义配合,条件中不能放变量,因为变量是程序运行时才会有,而条件编译是在程序编译之前运行
#include<stdio.h> #include"stu.h" #include<string.h> #define LENGTH 20 int main(int argc,const char * argv[]) { int k=0; #if LENGTH>10 k=sum(10,20); #elif LENGTH=20 k=sumAndMin(15,15, &k); #else k=sumNum(2,5); #endif
printf("%i",k); return0; } |
程序性能比普通函数中的if else条件判断提高,因为以上条件编译只会编译一行代码 |
注意:结尾一定要写#endif因为如果没有#endif标记条件编译结束,它会一直编译到程序结尾,这样就会编译不通过,很像sql中then else |
是否定义宏定义作为条件编译的条件
#if defined(LENGTH) printf("定义了宏名为LENGTH的宏定义"); #endif
#if !defined(LENGTH) printf("没有定义了宏名为LENGTH的宏定义"); #endif 上面的判断也可以用下面的方式 #ifdef LENGTH printf("定义了宏名为LENGTH的宏定义"); #endif
#ifndef LENGTH printf("没有定义了宏名为LENGTH的宏定义"); #endif |
Inlcude指令很像JSP中的inclue,直接把包含文件中的内容拷贝过来,我们经常会再Java项目中定义一些公共的JS文件或者我们自己开发的公共组件用include包含进来
#include<文件名> |
在C语言函数头文件所在目录中找 |
#include "文件名" |
先在程序源程序的目录中找,如果找不到,会去path(也就是系统环境变量配置的path)路径找,如果还是找不到才会去C语言函数头文件所在目录中找 |
可以嵌套包含,a.h包含b.h,b.h包含c.h,但是不可以递归相互包含a.h包含b.h,b.h包含a.h。
因为头文件可以嵌套包含,所以也带来了一些问题,比如头文件重复包含,这个时候我们就要使用宏定义来处理,这也是我们在XCODE中创建头文件的时候,XCODE会自动生成一段宏定义代码的原因,降低重复编译,提高效率
#ifndef testc_Student_h //如果没有定义宏testc_Student_h #define testc_Student_h //定义一个宏testc_Student_h void test(); #endif |
这样不管我们的头文件被包含多少次,但是程序只会编译一次头文件中的代码