乐趣区

关于c:C进阶22条件编译分析

Summary

1)条件编译的行为 相似于 C 语言中的if else; 条件编译是 预编译批示命令 ,用于管制 是否编译某段代码

2)预编译器 依据条件编译指令有抉择的 删除代码 ,所以编译器 不晓得 代码分支的存在

3)if else 在 运行期 进行分支判断,肯定会被 编进指标代码 条件编译指令 预编译期 进行分支判断,可能产生不同的代码段,因而编进指标代码的代码段不确定

4)能够通过 命令行定义宏 gcc -Dmacro=val file.cgcc -Dmacro file.c

5)#include 实质 是将曾经存在的文件内容 插入 到以后文件中;#include的间接蕴含同样会产生嵌入文件内容操作。条件编译指令 #ifndef _FILE_H_ #define _FILE_H #endif 能够解决这种 头文件反复蕴含 的谬误。

6)条件编译指令只是能够在同一个.c 文件中,避免反复蕴含 ;如果 头文件中有了符号的定义 ,然而在一个工程的 不同 c 文件里都进行了 include,这时候编译这两个文件也会有 反复定义 的谬误(因为两份 include 在各自的 c 文件里都定义了一个 global,在同一个全局作用域里定义了同名的 symbol)。所以,头文件中只申明、不定义

7)工程中的条件编译次要用于:不同的产品线共用一份代码 辨别编译产品的调试版和公布版

条件编译剖析

条件编译的行为 相似 于 C 语言中的 if...else...
条件编译是 预编译批示命令 ,用于管制 是否编译 某段代码;

1、条件编译于 if…else 的区别

  • 预编译器 依据条件编译指令有抉择的 删除代码 ,所以编译器 不晓得 代码分支的存在
  • if...else语句在 运行期 进行分支判断;条件编译指令 预编译期 进行分支判断
  • 能够通过 命令行定义宏 gcc -Dmacro=val file.c 或者gcc -Dmacro file.c
#define C1

int main()
{#if (C==1)
        printf("if true\n");
    #else
        printf("if false\n");
    #endif    

    return 0;
}
gcc -E test.c -o test.i
// 单步编译后失去的两头文件
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"

int main()
{printf("if true\n");
    return 0;
}

剖析:

  • 通过预编译期的解决后,失去的两头文件中 #if #else #endif 都被删掉了,这也阐明了下面的 预编译器依据条件编译指令有抉择的删除代码,所以编译器在拿到两头.i 文件后,基本就不晓得这些代码分支的存在。
  • 也阐明,#if #else #endif 是在预编译期进行判断 的,而if else 是在运行期才会判断
  • // 上述代码中去掉 #define C 1
    // 应用命令来定义宏
    gcc -DC=1 test.c
    编译后的运行后果为:if true
    
    gcc -DC test.c
    gcc -DC test.c
    编译后的运行后果为:if true

应用 #ifdef #else #endif 进行预编译分支判断:

  • #ifdef C
      printf("yes, defined");
    #else
      printf("no, undefined");
    #endif
    
    以上代码进行编译:gcc -DC test.c
    输入:yes, defined
    
    gcc test.c
    输入:no, undefined

2、条件编译解决头文件反复蕴含的编译谬误

  • #include 实质 是将曾经存在的文件内容 插入 到以后文件中
  • #include的间接蕴含同样会产生嵌入文件内容操作。
对以上代码进行单步编译
gcc -E test.c -o test.i
gcc -S test.i -o test.s

剖析:单步编译后,在两头.i 文件中,global 的定义呈现了 2 次,后续的编译过程天然会呈现重定义的谬误。

反复蕴含的解决形式:在头文件 test.h 和 global.h 中加上条件编译指令

#ifndef _HEADER_FILE_H_
#define _HEADER_FILE_H_
// SRC
#endif

留神 条件编译指令只是能够在同一个.c 文件中,避免反复蕴含 ;如果 头文件中有了符号的定义 ,然而在一个工程的 不同 c 文件里都进行了 include,这时候编译这两个文件也会有 反复定义 的谬误(因为两份 include 在各自的 c 文件里都定义了一个 global,在同一个全局作用域里定义了同名的 symbol)。所以,头文件中只申明、不定义
示例代码:

仍旧是下面的 test.c test.h global.h,再加一个 test2.c 文件,其中 #include "test.h"
执行:gcc test.c test2.c
输入:multiple definition of 'global'

3、条件编译工程中的利用

  • if else 编译器 解决,必然被编译进指标代码 #if #else #endif预编译器 解决,能够按不同的条件编译不同的代码段,因此 会产生不同的指标代码
  • 工程中的条件编译次要用于:不同的产品线共用一份代码 辨别编译产品的调试版和公布版

本文总结自“狄泰软件学院”唐佐林老师《C 语言进阶课程》。
如有错漏之处,恳请斧正。

退出移动版