条件编译 - 代码裁剪的工具

打印 上一主题 下一主题

主题 545|帖子 545|积分 1635

目录

条件编译 - 代码裁剪的工具

为何要有条件编译

条件编译重要是用于代码裁剪,通过代码裁剪,能够快速实现某种目的,如版本维护(free版本,pro版本等,功能裁剪,跨平台性等.

条件编译都在那些地方用?

举个例子
我们经常听说过,某某版程序是完全版/精简版,某某版应用是商用版/校园版,某某软件是根本版/扩展版等。
其实这些软件在公司内部都是同一个项目,是多个源文件构成的。所以,所谓的不同版本,其实就是那些功能的有无;在技术层面上,公司为了好维护,可以维护多种版本;如果是使用条件编译,想使用哪个版本,就使用哪种条件进行裁剪就行。
如著名的Linux内核,功能上也是使用条件编译进行功能裁剪的,来满足不同平台的软件。
见一见条件编译的代码
  1. int main()
  2. {
  3. #ifndef DEBUG
  4.    printf("hello debug\n");
  5. #elif RELEASE
  6.    printf("hello release\n");
  7. #else
  8.         printf("hello unknow\n");
  9. #endif
  10.    return 0;
  11. }
复制代码
宏是否被定义 vs 宏是否为真or假
  1. #define DEBUG    // 宏被定义
  2. #define DEBUG 1  // 宏被定义,且值为真
  3. #define DEBUG 0  // 宏被定义,且值为假
复制代码
宏为真假是在宏被定义之上的.

编译器也能够自动帮你加上宏

GCC
  1. 语法:gcc 源文件  -D 宏=值
  2. #   gcc test.c -D MACRO=1
复制代码
VS2023-VS2019



在vs平台上用的不多.



#ifdef/#ifndef

#ifdef/#ifndef用于检测宏是否被定义,有没有值,是真是假不重要
#ifdef 检测宏是否已经定义,是则保留,否则裁剪;#ifndef则相反
用法举例:

#ifdef/#ifndef一样平常只在头文件中使用

#if

#if的默认用法和#ifdef有一定区别,其他用法差不多,#if使用更频仍.
区别是#if如果定义了宏则要求必须要有值,没定义则当作假大概else.

注意事项

使用#if或#ifdef时,很容易会忘记写#endif.因为我们寻常写if-else没有这个end,很容易会类比忘记掉#endif.所以在使用条件编译时,先把#if - #endif写上,后面就不再容易遗漏了.



让#if和#ifdef/#ifndef完全一样

#if模拟#ifdef:
  1. #define MACRO
  2. int main()
  3. {
  4. #if defined(MACRO)
  5.         puts("MACRO defined!");
  6. #else
  7.         puts("MACRO undefined!");
  8. #endif
  9.         return 0;
  10. }
复制代码
程序运行结果:

如果是未定义呢? 没有别的名词,加个逻辑反就好啦


条件编译也支持嵌套
  1. #include<stdio.h>
  2. #include<math.h>
  3. #define C   
  4. #define CPP   
  5. int main()     
  6. {            
  7. #if defined(C)   
  8.     #if defined(CPP)   
  9.         puts("hello CPP");   
  10.     #endif                  
  11.   puts("hello C");   
  12. #else                 
  13.   puts("hello other");   
  14. #endif                    
  15.   return 0;   
  16. }  
复制代码

解释掉#define C后

可以证明,条件编译是支持嵌套的.
不过,使用嵌套的代码阅读体验是比力差的,一样平常不建议使用嵌套,下面还有其他更好的代码写法推荐.



一个使用#if defined能起到很好优化的用法

[引用](C语言#if defined高级用法-CSDN博客)
在一个需要完成“多个宏定义来共同控制同一代码分支”的情况下,例如

  • TEST_1 或 TEST_2被定义,则选择执行1,2
  1. #ifndef TEST_1
  2. #define TEST_1
  3. #endif
  4. #ifdef TEST_1
  5.         puts("1");
  6. #else
  7.         #ifdef TEST_2
  8.                 puts("1");
  9.         #else
  10.                 puts("2");
  11.         #endif
  12. #endif
复制代码

  • 大概, TEST_1和TEST_2均未定义,则选择执行1,否则执行2
  1. #ifndef TEST_1
  2.         puts("1");
  3. #else
  4.         #ifndef TEST_2
  5.                 puts("1");
  6.         #else
  7.                 puts("2");
  8.         #endif
  9. #endif
复制代码
这样的代码看起来是比力冗余的,不好阅读,因为#ifdef是没有对应的"else if",我们只能采取这样的方式写.对比到一样平常使用的if-else,if()内可以是一个表达式,那#ifdef能否也能将宏定义组织成表达式呢?
看一下代码
  1. #ifdef TEST_1 || TEST_2
  2.         puts("1");
  3. #else
  4.         puts("2");
  5. #endif
复制代码
这样的代码看起来是更简洁,更优雅.但它是错误的.

因为ifdef和ifndef仅能跟一个宏定义参数,而不能使用表达式

虽然在vs下可以运行

但是我们不推荐这样不能跨平台的代码.

因为#if需要判断真假而具有盘算表达式的功能,
因此,使用#if defined 和 #if !defined是更好的选择.

  • TEST_1 或 TEST_2被定义,则选择执行1,否则执行2
  1. #if defined TEST_1 || defined TEST_2
  2.         puts("1");
  3. #else
  4.         puts("2");
  5. #endif
复制代码

  • TEST_1 或 TEST_2未被定义,则选择执行1,否则执行2
  1. #if !defined TEST_1 || !defined TEST_2
  2.         puts("1");
  3. #else
  4.         puts("2");
  5. #endif
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

欢乐狗

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表