C语言 深入讲解条件编译的用处

  目录

  一、基本概念

  下面看一段简单的条件编译的代码:

  #include

  #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;

  }

  下面为输出结果:

  可以输入gcc -E Test.c -o file.i 命令,看看预编译阶段发生了什么,下面是部分输出结果:

  # 2 "Test.c" 2

  int main()

  {

  const char* s;

  s = "This is first printf...

  ";

  printf("%s", s);

  return 0;

  }

  可以看到宏定义和条件编译都没有了,由相应内容取而代之。

  二、条件编译的本质

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

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

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

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

  可以通过命令行定义宏

  下面看一个通过命令行定义宏的代码:

  #include

  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 -DC Test.c,输出结果如下:

  三、#include 的本质

  这就出现一个问题,间接包含同一个头文件是否会产生编译错误?

  下面就来通过一段代码深入探究:

  global.h:

  // global.h

  int global = 10;

  test.h:

  // test.h

  #include "global.h"

  const char* NAME = "test.h";

  char* hello_world()

  {

  return "hello world!

  ";

  }

  test.c:

  #include

  #include "test.h"

  #include "global.h"

  int main()

  {

  const char* s = hello_world();

  int g = global;

  printf("%s

  ", NAME);

  printf("%d

  ", g);

  return 0;

  }

  编译后编译器报错,global 重定义:

  为什么 global 会重定义呢?下面开始单步编译,输入gcc -E test.c -o test.i,输出部分结果如下:

  # 2 "test.c" 2

  # 1 "test.h" 1

  # 1 "global.h" 1

  int global = 10;

  # 4 "test.h" 2

  const char* NAME = "test.h";

  char* hello_world()

  {

  return "hello world!

  ";

  }

  # 3 "test.c" 2

  # 1 "global.h" 1

  int global = 10;

  # 4 "test.c" 2

  int main()

  {

  const char* s = hello_world();

  int g = global;

  printf("%s

  ", NAME);

  printf("%d

  ", g);

  return 0;

  }

  这样就很明显了,程序先将 test.h 里面的东西复制进 test.c,由于 test.h 里面有一个 include "global.h",就把int global = 10; 复制过来,然后复制

  const char* NAME = "test.h";

  char* hello_world()

  {undefined

  return "hello world!

  ";

  }

  在然后由于test.c 里面又定义一个#include "global.h",又把int global = 10; 复制过来,造成了重复定义。

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

  #ifndef _HEADER_FILE_H_

  #define _HEADER_FILE_H_

  //source code

  #endif

  如果没有定义 header_file.h,则定义,且执行里面的代码;否则,如果定义了,里面的代码就不会执行。

  所以上述代码中可以这么改:

  global.h:

  // global.h

  #ifndef _GLOBAL_H_

  #define _GLOBAL_H_

  int global = 10;

  #endif

  test.h:

  // test.h

  #ifndef _TEST_H_

  #define _TEST_H_

  #include "global.h"

  const char* NAME = "test.h";

  char* hello_world()

  {

  return "hello world!

  ";

  }

  #endif

  这样编译就能通过了

  四、条件编译的意义

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

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

  实际工程中条件编译主要用于以下两种情况:

  下面看一段产品线区分及调试代码:

  product.h:

  #define DEBUG 1

  #define HIGH 1

  test.c:

  #include

  #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;

  }

  宏 DEBUG 是指产品是调试版还是发布版,调试版为 1,发布版为 0, 宏 HIGH指的是产品是高端产品还是低端产品,高端产品为 1,低端产品为 0

  如果我们想测试调试版的高端产品,令 DEBUG 为 1,HIGH为 0 即可:

  同理,我们想测试发布版的低端产品,令 DEBUG 为 0,HIGH为 0 即可:

  五、小结

  到此这篇关于C语言 深入讲解条件编译的用处的文章就介绍到这了,更多相关C语言 条件编译内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

  您可能感兴趣的文章: