15 条件编译

1 条件编译的基本概念

  • 条件编译是宏定义和预处理器的应用

  • 应用场合:开发不同档次的产品(低端/中端/高端) => 同一份代码产生不同的产品

  • 条件编译的行为类似于C语言中的 if...else...

  • 条件编译本质是预编译指示命令,用于控制是否编译某段代码

  • 示例1:预编译指令

    • Code

      #include <stdio.h>
      
      #define C 1
      
      int main()
      {
          const char* s;
      
          #if( C == 1 )
              s = "This is first printf...
      ";
          #else
              s = "This is second printf...
      ";
          #endif
      
          printf("%s", s);
          
          return 0;
      }
      // 输出结果
      This is first printf...
      
    • 单步编译:gcc -E test.c -o test.i

      int main()
      {
          const char* s;
              s = "This is first printf...
      ";
          
          
          
          return 0;
      }
      

2 条件编译的本质

  • 预编译器根据条件编译指令有选择的删除代码

  • 编译器不知道代码分支的存在

  • if...else... 语句在运行期进行分支判断

  • 条件编译指令在预编译期进行分支判断

  • 可以通过命令行定义宏:-D,而不用 #define 来定义

  • 示例2:通过命令行定义宏

    #include <stdio.h>
    
    int main()
    {
        const char* s;
    
        #ifdef C
            s = "This is first printf...
    ";
        #else
            s = "This is second printf...
    ";
        #endif
    
        printf("%s", s);
        
        return 0;
    }
    
    • GCC 直接编译运行结果:This is second printf...
    • 通过命令行定义宏编译:gcc -DC=1 test.c -o test ,运行结果:This is first printf...

3 #include 的本质

  • #include 的本质是将已经存在的文件内容嵌入到当前文件中

  • #include 的间接包含同样会产生嵌入文件内容的操作

  • 间接包含同一个头文件会产生编译错误

  • 示例3:重复包含头文件

    // test.c
    #include <stdio.h>
    #include "test.h"
    #include "global.h"
    
    int main()
    {
        const char* s = hello_world();
        int g = global;
        
        printf("%s
    ", NAME);
        printf("%d
    ", g);
        
        return 0;
    }
    
    
    // test.h
    #ifndef _TEST_H_
    #define _TEST_H_
    #include "global.h"
    const char* NAME = "test.h";
    char* hello_world()
    {    
        return "Hello world!
    ";
    }
    #endif
    
    
    // global.h
    #ifndef _GLOBAL_H_
    #define _GLOBAL_H_
    int global = 10;
    #endif
    
    • GCC 编译

      In file included from test.c:3:
      global.h:2: error: redefinition of 'global'
      global.h:2: error: previous definition of 'global' was here
      
    • 单步编译:gcc -E test.c -o test.i ,可以发现因为头文件的重复包含,global 变量被重复定义了

  • 条件编译可以解决头文件重复包含的编译错误

    // test.h
    #ifndef _TEST_H_
    #define _TEST_H_
    #include "global.h"
    const char* NAME = "test.h";
    char* hello_world()
    {    
        return "Hello world!
    ";
    }
    #endif
    
    
    // global.h
    #ifndef _GLOBAL_H_
    #define _GLOBAL_H_
    int global = 10;
    #endif
    
    // 输出结果
    test.h
    10
    

4 条件编译的意义

  • 条件编译可以按不同的条件编译不同的代码段,因而可以产生不同的目标代码

  • #if... #else...#endif 被预编译器处理,而 if...else... 语句被编译器处理,必然被编译进目标代码

  • 条件编译主要应用于

    • 不同的产品线共用一份代码
    • 区分编译产品的调试版和发布版
  • 示例4:条件编译应用

    • DEBUG 宏的值决定是 Debug 版本的还是 Release 的,所打印的日志不一样
    • HIGH 宏的值决定是高水平的还是水平的版本,所提供的功能不一样
    #include <stdio.h>
    #include "product.h"
    
    #if DEBUG
        #define LOG(s) printf("[%s:%d] %s
    ", __FILE__, __LINE__, s)
    #else
        #define LOG(s) NULL
    #endif
    
    #if HIGH
    void f()
    {
        printf("This is the high level product!
    ");
    }
    #else
    void f()
    {
    }
    #endif
    
    int main()
    {
        LOG("Enter main() ...");
        
        f();
        
        printf("1. Query Information.
    ");
        printf("2. Record Information.
    ");
        printf("3. Delete Information.
    ");
        
        #if HIGH
        printf("4. High Level Query.
    ");
        printf("5. Mannul Service.
    ");
        printf("6. Exit.
    ");
        #else
        printf("4. Exit.
    ");
        #endif
        
        LOG("Exit main() ...");
        
        return 0;
    }
    
    
    //product.h
    #define DEBUG 1
    #define HIGH  1
    
原文地址:https://www.cnblogs.com/bky-hbq/p/13604494.html