首页 > 其他分享 >条件编译 - 代码裁剪的工具 --进阶C语言

条件编译 - 代码裁剪的工具 --进阶C语言

时间:2024-09-15 16:02:42浏览次数:1  
标签:进阶 puts -- endif C语言 编译 ifdef TEST else

目录

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

为何要有条件编译

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


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

举个例子

我们经常听说过,某某版程序是完全版/精简版,某某版应用是商用版/校园版,某某软件是基础版/扩展版等。

其实这些软件在公司内部都是同一个项目,是多个源文件构成的。所以,所谓的不同版本,其实就是那些功能的有无;在技术层面上,公司为了好维护,可以维护多种版本;如果是使用条件编译,想使用哪个版本,就使用哪种条件进行裁剪就行。

如著名的Linux内核,功能上也是使用条件编译进行功能裁剪的,来满足不同平台的软件。

见一见条件编译的代码

int main()
{
#ifndef DEBUG
    printf("hello debug\n");
#elif RELEASE
    printf("hello release\n");
#else 
	printf("hello unknow\n");
#endif
    return 0;
}

宏是否被定义 vs 宏是否为真or假

#define DEBUG    // 宏被定义

#define DEBUG 1  // 宏被定义,且值为真

#define DEBUG 0  // 宏被定义,且值为假

宏为真假是在宏被定义之上的.


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

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

image-20240508153946278

image-20240508154007078

在vs平台上用的不多.



#ifdef/#ifndef

#ifdef/#ifndef用于检测宏是否被定义,有没有值,是真是假不重要

#ifdef 检测宏是否已经定义,是则保留,否则裁剪;#ifndef则相反

用法举例:

image-20240507171846307

#ifdef/#ifndef一般只在头文件中使用


#if

#if的默认用法和#ifdef有一定区别,其他用法差不多,#if使用更频繁.

区别是#if如果定义了宏则要求必须要有值,没定义则当作假或者else.


注意事项

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



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

#if模拟#ifdef:

#define MACRO
int main()
{
#if defined(MACRO)
	puts("MACRO defined!");
#else
	puts("MACRO undefined!");
#endif
	return 0;
}

程序运行结果:

image-20240508160951829

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

image-20240508170933763


条件编译也支持嵌套

#include<stdio.h>
#include<math.h>

#define C    
#define CPP    

int main()     
{             
#if defined(C)    
    #if defined(CPP)    
        puts("hello CPP");    
    #endif                  
  puts("hello C");    
#else                 
  puts("hello other");    
#endif                    
  return 0;    
}  

image-20240508173148156

注释掉#define C

image-20240508173245666

可以证明,条件编译是支持嵌套的.

不过,使用嵌套的代码阅读体验是比较差的,一般不建议使用嵌套,下面还有其他更好的代码写法推荐.



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

[引用](C语言#if defined高级用法-CSDN博客)

在一个需要完成“多个宏定义来共同控制同一代码分支”的情况下,例如

  • TEST_1 或 TEST_2被定义,则选择执行1,2
#ifndef TEST_1
#define TEST_1
#endif

#ifdef TEST_1
	puts("1");
#else
	#ifdef TEST_2
		puts("1");
	#else
		puts("2");
	#endif
#endif
  • 或者, TEST_1和TEST_2均未定义,则选择执行1,否则执行2
#ifndef TEST_1
	puts("1");
#else
	#ifndef TEST_2
		puts("1");
	#else
		puts("2");
	#endif
#endif

这样的代码看起来是比较冗余的,不好阅读,因为#ifdef是没有对应的"else if",我们只能采用这样的方式写.对比到一般使用的if-else,if()内可以是一个表达式,那#ifdef能否也能将宏定义组织成表达式呢?

看一下代码

#ifdef TEST_1 || TEST_2
	puts("1");
#else
	puts("2");
#endif

这样的代码看起来是更简洁,更优雅.但它是错误的.

image-20240508163628082

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


虽然在vs下可以运行

image-20240508163859587

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


因为#if需要判断真假而具有计算表达式的功能,

因此,使用#if defined#if !defined更好的选择.

  • TEST_1 或 TEST_2被定义,则选择执行1,否则执行2
#if defined TEST_1 || defined TEST_2
	puts("1");
#else
	puts("2");
#endif
  • TEST_1 或 TEST_2未被定义,则选择执行1,否则执行2
#if !defined TEST_1 || !defined TEST_2
	puts("1");
#else
	puts("2");
#endif


标签:进阶,puts,--,endif,C语言,编译,ifdef,TEST,else
From: https://www.cnblogs.com/DSCL-ing/p/18414575

相关文章

  • MySQL 大表拆分
    概述在实际工作中,在关系数据库(MySQL、PostgreSQL)的单表数据量上亿后,往往会出现查询和分析变慢甚至无法执行统计分析的情况。这时就需要将大表拆分为多个小表,将小表分布在多个数据库上,形成一个数据库集群。这样的话,一条SQL统计语句就可以在多台服务器上并发执行,然后将执行结果汇......
  • Redis 管道技术
    概述Redis是基于请求/响应协议的TCP服务。在客户端向服务器发送一个查询请求后,需要监听Socket的返回结果,该监听过程一直阻塞,直到服务器有结果返回。如果一次请求延迟20ms,则多次请求的网络延迟会不断累加。也就是说,Redis的性能瓶颈主要体现在网络延迟上Redis的管道技术指......
  • ZR24NOIP1B. 数数
    ZR24NOIP1B.数数给你一个长度为\(n\le1600\)的二进制数,其中某些位未知,是?。问?的所有取值得到的\(x\),\([0,x-1]\)中不含长度为\(k\le20\)的回文串的数字(含前导\(0\))的个数的和。首先显然是数位DP。考虑从高位枚举到低位,假设没有?,状态记位数\((1600)\)和是否顶......
  • 【含文档】基于Springboot+Vue的甘肃旅游服务平台(含源码数据库)
    1.开发环境开发系统:Windows10/11架构模式:MVC/前后端分离JDK版本:JavaJDK1.8开发工具:IDEA数据库版本:mysql5.7或8.0数据库可视化工具:navicat服务器:SpringBoot自带apachetomcat主要技术:Java,Springboot,mybatis,mysql,vue2.视频演示地址3.功能这个系......
  • 【含文档】基于Springboot+Vue的二手物品交易的设计与实现(含源码数据库)
    1.开发环境开发系统:Windows10/11架构模式:MVC/前后端分离JDK版本:JavaJDK1.8开发工具:IDEA数据库版本:mysql5.7或8.0数据库可视化工具:navicat服务器:SpringBoot自带apachetomcat主要技术:Java,Springboot,mybatis,mysql,vue2.视频演示地址3.功能这个系......
  • 学习Python第一步,先安装Python,最新安装教程!
      随着人工智能,网络爬虫,大数据分析等业务模式的流行,Python依靠拥有各种开源库,且入门容易等特性越来越火爆。想到就去做,赶紧下载Python学习起来,本文将详细介绍Python编程环境的搭建。Python的版本选择目前Python有两个版本,一个是2.x,一个是3.x,这两个版本并不兼容。由于在20......
  • 【计算机网络 - 基础问题】每日 3 题(六)
    ✍个人博客:Pandaconda-CSDN博客......
  • 【计算机网络 - 基础问题】每日 3 题(五)
    ✍个人博客:Pandaconda-CSDN博客......
  • 13 Midjourney从零到商用·进阶篇:灯光、角度与风格等精细控制方法
    在前面我们了解了提示词的书写,那么如何利用提示词来精确控制生成画面的灯光、角度与风格呢?在本篇文章中我么一起来探讨一下。一、灯光在摄影中,对灯光的要求都是非常高的。灯光能对人物、动物、物体、场景等进行修饰。每一种微小的的灯光变化都能是画面呈现出不同的效果......
  • 【Python基础学习】16个必知必会的Python教程
    介绍Python是一门用途广泛的编程语言,它具有大量的库和框架。有一些鲜为人知的Python编码技巧和库可以让你作为开发人员的工作更为轻松,编写代码更高效。本文中将探讨一些鲜为人知的Python技巧,这些技巧非常有用,但并不广为人知。通过学习和使用这些技巧,可以帮你节省时......