C 预编译
1. 文件包含2. 条件编译2.1 #if #ifdef #endif等2.2 #ifdef __cplusplus extern “C” { #endif 3. 布局控制4. 宏替换4.1 宏定义4.2 宏函数预处理的主要作用就是通过内建功能对一个资源进行等价替换,从而对源文件实现代码文本的替换工作,比如文本替换、文件包含、删除部分代码等,以减少重复运算过程,提高程序运行效率。最常见的预处理有:文件包含,条件编译、布局控制和宏替换4种。
1. 文件包含
#include 是一种最为常见的预处理,主要是做为文件的引用组合源程序正文。
文件包含有两种格式,分别是: #include “file” 和 #include< file >
这两格式的区别在于:
使用双引号,系统首先到当前目录下查找被包含的文件,如果没找到,再到系统指定的 " 包含文件目录 " (由用户在配置环境时设置)去找。使用尖括号:直接到系统指定的 " 包含文件目录 " 去查找。
因此,通常使用双引号比较保险。
2. 条件编译
2.1 #if #ifdef #endif等
一般情况下,源程序中所有的代码都会参加编译,但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。
#if,#ifdef,#endif,#undef等也是比较常见条件编译的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
2.2 #ifdef __cplusplus extern “C” { #endif
在cpp文件中会出现如下片段:
#ifdef __cplusplusextern “C” {#endif//代码#ifdef __cplusplus }#endif
它的作用在于:
对C++函数的重载处理。在C++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等。而在C中,只是简单的函数名字而已,不会加入其他的信息。也就是说:C++和C对产生的函数名字的处理是不一样的。
为了在C++中尽可能的支持C,extern “C” 就是其中的一个策略。为了在C++代码中调用C的库文件,就需要用extern “C” 来告诉编译器,用C的方式来链接它们。
使用过程中,会用到#ifdef __cplusplus #endif 对头文件进行定义声明,表示的意思是:如果这是一段cpp的代码,那么加入extern “C” {" 和 " }"处理其中的代码,其中{ }内部的代码是通过extern "C"进行处理,所以在所有的头文件引用中,如果是CPP代码文件,就会自动调用g++进行编译,但是如果是C代码文件,自动调用gcc进行编译。
3. 布局控制
#progma,主要功能是为编译程序提供非常规的控制流信息。
4. 宏替换
4.1 宏定义
#define 与 typedef 的作用域区别:主要体现在函数中定义,#define在函数中定义可以作用于整个文件的定义之后部分,而在函数中定义的 typedef 类型只作用于函数中定义以下的部分。
4.2 宏函数
宏函数不是真正的函数,而是带参数的宏,只是使用方法像函数而已。
在代码中使用宏函数,预处理时会经历两次替换,第一次把宏函数替换成它后面的一串代码、表达式,第二次把宏函数中的参数替换到表达式中。
什么样的代码适合封装成宏函数?
1、代码量少,即使多次使用也不会造成代码段过度冗余。
2、调用次数,但执行次数多。
3、对返回值没有要求。
宏函数的优缺点:
优:1、执行速度快,它不是真正的函数调用,而是代码替换,不会经历传参、跳转、返回值。
2、不会检查参数的类型,因此通用性强。
缺:1、由于它不是真正的函数调用,而是代码替换,每使用一次,就会替换出一份代码,会造成代码冗余、编译速度慢、可执行文件变大。
2、没有返回值,最多可以有个执行结果。
3、类型检查不严格,安全性低。
4、无法进行递归调用。