• 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
      
  • 相关阅读:
    Android开发之EditText属性详解
    android开发如何在页面之间传参
    jquery中attr和prop的区别
    Laravel 5.2--改变数据库字段值,编辑时候,默认选中
    Laravel 5.2--git冲突error: Your local changes to the following files would be overwritten by merge:
    Laravel 5.2--如何让表单提交错误,不清空?
    Apache 和 Tomcat联系和区别
    mac 上如何安装非app store上的下载的软件-------打开未知来源
    &#65279导致页面顶部空白一行解决方法
    面向对象设计的三个基本特征
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13604494.html
Copyright © 2020-2023  润新知