【c++从菜鸡到王者】第五篇-( 全网最精华)条件编译ifdef的用法

本文详细介绍了C++中的预处理指令,包括条件编译和宏定义。条件编译如#ifdef、 ifndef等用于根据宏定义选择性编译代码,减少目标程序长度。宏定义分为对象宏和函数宏,前者常用于定义常量,后者提供类似函数的功能但无需额外开销。建议使用const或enum替代#define定义常量,用inline函数替换函数宏以提高类型安全性和代码质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 预处理指令

    预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

    预处理指令是在编译器进行编译之前进行的操作.预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。

    //常见的预处理命令如下
    #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的用法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值