-
预处理指令
预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
预处理指令是在编译器进行编译之前进行的操作.预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。
//常见的预处理命令如下 #include 包含一个源文件 #define 定义一个预处理宏 #undef 取消已定义宏 #if 如果条件为真,则执行以下代码 #ifdef 如果宏已经定义,则编译下面的代码 #ifndef 如果宏没有被定义,则编译下面的代码 #elif 如果前面if的条件为假,当前条件为真,则编译下面的代码,相当于c语言中else-if #endif #if,#ifdef,#ifndef的结束标志 #else 与#if,#ifdef,#ifndef对应,如果这些条件不满足则执行#else后面的代码
-
我们先理解什么是条件编译?
条件编译是根据实际定义宏(某类条件)进行代码静态编译的手段。可根据表达式的值或某个特定宏是否被定义来确定编译条件。最常见的条件编译是防止重复包含头文件的宏。
-
主要了解#ifdef,#ifndef,#define
-
#ifdef ABC // ... codes while definded ABC #elif (CODE_VERSION > 2) // ... codes while CODE_VERSION > 2 #else // ... remained cases #endif // #ifdef ABC //如果不需要多条件编译的话,#elif,#else,可省略 //有人会问:不用条件编译命令而直接用if语句也能达到要求,用条件编译命令有什么好处呢?的确,此问题完全可以不用条件编译处理,但那样做目标程序长(因为所有语句都编译),而采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译段比较多时,目标程序长度可以大大减少。 ------------------------------------------------------------------------------------- //头文件中的#ifdef是个非常重要的东西——避免重复包含。具体代码如下 #ifndef <标识> #define <标识> ...... ...... #endif //<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h #ifndef _STDIO_H_ #define _STDIO_H_ ...... #endif ----------------------------------------------------------------------------------
-
#define __ 定义一个宏
宏定义按照是否带参数分为对象宏与函数宏
对象宏:不带参数的宏。多用于定义常量。通用表示
// 常量定义 #define MAX_LENGTH 100 // 通用标识,日志输出宏 #define SLog printf // 预编译宏 #define _DEBUG
对于单纯常量为了提高效率我们尽量使用const对象或enums替换#defines
//注意 1.当我们定义常量指针的时候,由于常量定义式一般放在头文件中,被不同的源代码包含,所以我们有必要把指针设置为const,例如: const char*const authorName=“xxx”; const std::string authorname=("xxx"); 2.class专属常量,为了将常量的作用域限制在class内,必须让它的一个成员为static class xxx{ private: static const int number=5;//常量声明式 int scores[number];//使用常量 ... }; //注意旧编译器可能不支持上述语法,不允许static成员在其声明式上获得初值,如果你的编译器不支持上面的语法,可以把初值放入定义式里 class xxx{ private: static const int numbers; ... }; const int xxx:nubers=5; //唯一的例外就是当你的class在编译的时候确实需要一个常量值,比如上面的数组声明式中,编译器坚持的要在编译期间知道数组的大小,但是可能你的编译器又错误的不允许初值设定,那么就可以使用"the enum hack",其理论基础是:一个属于枚举类型的值可以当作ints使用: class xxx{ private: enum {number=5}; int scores[number];//使用常量 ... }; //为什么要使用它:第一:想define一样不会导致非必要的内存分配 ;第二:许多代码的用到了它,所以你必须要认识它,enum hack 是模板元编程的基础技术
函数宏:带参数的宏,提高代码运行效率,不会招致函数调用带来的格外开销
#define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b)) //记住,当你要写出这种宏的时候,要为宏中所有实参添上小括号.
但是大多数c++程序不会使用函数宏,而是使用tempalete inline函数
template <typename T> inline void CALLWITHMAX(const T& a,const T&b){ f(a>b?a:b); } //有了这个函数,你可以享受宏带来的效率以及一般函数的所有可预料的行为和类型安全性
-
总结:对于单纯常量,最好以const或enum取代#define;对于函数宏,最好改用inline函数替换#define
更多细节参考:(1条消息) 条件编译#ifdef的妙用详解_透彻_MARS_Turing的博客-优快云博客_ifdef的用法