关于预处理

1、宏定义是在预处理的时候发生的,可见编译器根本就不认识#define,

编译器根本不知道还有个宏定义。

typedef是由编译器来处理而不是预处理器处理的,这就是两者的本质区别;


2、头文件包含的真实含义就是:在#include<xx.h>的那一行,
将xx.h这个头文件的内容原地展开替换这一行#include语句。过程在预处理中进行。


3、在预处理阶段,预处理器会拿掉程序中所有的注释语句,到了编译器编译阶段程序中其实已经没有注释了。


宏定义注意的两个点:

宏定义示例1:MAX宏,求2个数中较大的一个
#define MAX(a, b) (((a)>(b)) ? (a) : (b))
关键:
第一点:要想到使用三目运算符来完成。
第二点:注意括号的使用


宏定义示例2:SEC_PER_YEAR,用宏定义表示一年中有多少秒
#define SEC_PER_YEAR (365*24*60*60UL)
关键:
第一点:当一个数字直接出现在程序中时,它的是类型默认是int
第二点:一年有多少秒,这个数字刚好超过了int类型存储的范围


4、宏定义是在预处理期间处理的,而函数是在编译期间处理的。这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行,执行完后再跳转回来。
因此宏定义没有调用开销;函数有比较大的调用开销。所以宏定义和函数相比,优势就是没有调用开销,没有传参开销,所以当函数体很短(尤其是只有一句话时)可以用宏定义来替代,这样效率高。


5、带参宏和带参函数的一个重要差别就是:宏定义不会检查参数的类型,返回值也不会附带类型;而函数有明确的参数类型和返回值类型。当我们调用函数时编译器会帮我们做参数的静态类型检查,如果编译器发现我们实际传参和参数声明不同时会报警告或错误。用宏的时候程序员必须很注意实际传参和宏所希望的参数类型一致,否则可能编译不报错但是运行有误。

总结:宏和函数各有千秋,各有优劣。总的来说,如果代码比较多用函数适合而且不影响效率;但是对于那些只有一两句话的函数开销就太大了,适合用带参宏。但是用带参宏又有缺点:不检查参数类型。结合两者的优点,就是我们的内联函数。

6、内联函数和inline关键字
(1)内联函数通过在函数定义前加inline关键字实现。
(2)内联函数本质上是函数,所以有函数的优点(内联函数是编译器负责处理的,编译器可以帮我们做参数的静态类型检查);但是他同时也有带参宏的优点(不用调用开销,而是原地展开)。所以几乎可以这样认为:内联函数就是带了参数静态类型检查的宏。
(3)当我们的函数内函数体很短(譬如只有一两句话)的时候,我们又希望利用编译器的参数类型检查来排错,我还希望没有调用开销时,最适合使用内联函数。


4.6.4.3、宏定义来实现条件编译(#define #undef #ifdef)
(1)程序有DEBUG版本和RELEASE版本,区别就是编译时有无定义DEBUG宏。

#define DEBUG
#undef DEBUG // 注销一个宏。如果前面有定义这个宏则取消这个宏


#ifdef DEBUG
#define debug(x) printf(x)
#else
#define debug(x)
#endif

猜你喜欢

转载自blog.csdn.net/amumu_123/article/details/78535328