0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

"最常见"却又"最不常用"的三个预编译

Q4MP_gh_c472c21 来源:最后一个bug 作者:bug菌 2020-11-16 15:55 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1

#error 与#warning

谈到预编译大家常用的有#if、#else、#ifdef、#ifndef、#endif等等条件编译选项。

然而在我们阅读一些大型的代码或者库的时候,一般都会看到有#error和#warning,可能有些小伙伴一扫而过并没有了解清楚这些预编译指令到底该怎么用,写了很久的代码估计也重来没有敲过他们。

#error / #warning

形式 :#error / #warningmessage

作用 :生成一个编译错误事件并停止编译/发出警告信息

注意 :message可以不需要双引号。

参考demo:

#include #include //#defineconfigUART_N5 #ifndefconfigUART_N #errorconfigUART_Nmustdefine //#error"configUARTmustdefine" //#warning"configUARTmustdefine" #endif #ifconfigUART_N>4 #errorconfigUART_Nmustnotbelessthan4 //#error"configUART_Nmustnotbelessthan4" //#warning"configUART_Nmustnotbelessthan4" #endif /*************************************** *Fuction:进行预编译测试 *Author:(最后一个bug) **************************************/ intmain(intargc,char*argv[]){ printf("公众号;最后一个bug "); return0; }

输出结果:

编译失败,无法生成可执行文件

上面是放开宏,且使用warning的情况,无其他错误的情况下可以生成可执行文件。

解释一下:

通过上面的测试代码可以了解到,通过配合条件预编译#if等,#error和#warning能够在编译过程中分别以错误和告警的形式提醒开发人员注意相关代码设计问题,从而保证代码正确性。

这样对于发布一些庞大的库代码时,为了让开发人员正确的使用库,这些提示会帮助他更好的移植代码。

那么经常有很多小伙伴编译出来的代码有一大堆warning,总是觉得warning关系不大,然而warning也是分不同类型的,对于一些未使用的变量倒关系不大,其他情况还是要认真对待,最好是做到"0 Error,0 warning".

2

#undef

#undef标识符用于把前面的宏定义名取消,别看这宏用得不多,作用可大着呢,下面我简单举几个例子:

1

局部宏定义

一旦定义了宏,那么该文件中往下所有的代码都可以使用该宏,即使是函数内部,这样导致宏比较混乱,如下面代码:

参考demo:

#include #include #defineconfigRatio10 /*************************************** *Fuction:获得传感器电压值 *Author:(最后一个bug) **************************************/ intGetSensorVolt(void) { #defineconfigRatio1 intret=0; ret=configRatio*1024;//比例因子*AD值 returnret; //#undefconfigRatio } /*************************************** *Fuction:获得传感器电压值 *Author:(最后一个bug) **************************************/ intGetSensorCurr(void) { #defineconfigRatio2 intret=0; ret=configRatio*1024;//比例因子*AD值 returnret; //#undefconfigRatio } /*************************************** *Fuction:进行预编译测试 *Author:(最后一个bug) **************************************/ intmain(intargc,char*argv[]){ printf("configRatio=%d ",configRatio);//报宏未定义 printf("GetSensorVolt=%d ",GetSensorVolt()); printf("GetSensorCurr=%d ",GetSensorCurr()); printf("公众号;最后一个bug "); return0; }

输出结果:

解释一下:

假如我们没有注意到函数内部的同名宏定义,当然告警也没管,那么在main函数中使用同名宏定义就可能不是我们期待的最上面的宏定义,造成程序bug。

所以我们可以使用#undef来限制每个宏的作用域,如果每个函数内部都使用了#undef,那么main函数中再使用会报宏没有定义,这样便可以找到问题,当然也可以通过警告了解到。

2

选择接口

通过宏来切换不同的接口供程序使用:

参考demo:

#include #include #include #defineDEV_SPI #include"Drive.h" #undefDEV_SPI /*************************************** *Fuction:进行预编译测试 *Author:(最后一个bug) **************************************/ intmain(intargc,char*argv[]){ char*strbug="thelastbug"; SendData(strbug); ProcessData(strbug); printf("公众号;最后一个bug "); return0; }

#include #ifdefDEV_UART #defineSendData(s)printf("UARTSend:%s ",s) #defineProcessData(s)printf("UARTProcess:%s ",s) #endif #ifdefDEV_CAN #defineSendData(s)printf("CANSend:%s ",s) #defineProcessData(s)printf("CANProcess:%s ",s) #endif #ifdefDEV_SPI #defineSendData(s)printf("SpiSend:%s ",s) #defineProcessData(s)printf("SpiProcess:%s ",s) #endif

输出结果:

3

自定义接口

当多个人维护一套代码的时候,有些同事喜欢调用库函数接口,而有些同事喜欢调用自定义接口,为了方便统一使用自定义接口或者库接口,我们会进行如下操作:

参考demo:

#include #include #include #include"Drive.h" //#undefprintf /*************************************** *Fuction:进行预编译测试 *Author:(最后一个bug) **************************************/ intmain(intargc,char*argv[]){ char*strbug="thelastbug"; printf("公众号;最后一个bug "); return0; }

#ifndef__DRIVE_H__ #define__DRIVE_H__ #defineprintfprintf("pleaseuseKprintf! "); externvoidKprintf(char*str); #endif

输出结果:

这样下面的代码你就只能够使用Kprintf来进行输出打印,而当我们放开注释掉的宏,这样就又可以使用printf了,还是比较方便的。

责任编辑:lq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4983

    浏览量

    74543
  • 编译
    +关注

    关注

    0

    文章

    697

    浏览量

    35343

原文标题:"最常见"却又"最不常用"的三个预编译

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    做单片机开发,新手最容易犯的 3 选型误区

    很多做硬件和软件开发的新手,一开始选型很容易走弯路,浪费打样成本和时间。 分享三个最常见的误区: 一味追求高配置,功能用不上,反而增加成本。 不看实际功耗需求,做电池产品选错系列,续航拉胯。 只看
    发表于 05-20 14:48

    EtherCAT 主站开发,国内工程师最常问的三个核心问题

    往往是难点。深耕工业通讯多年,我们总结了国内工程师在私信和技术交流中最常问的三个核心问题。今天就通过这篇QA,带大家彻底摸清EtherCAT主站开发的门道。一、Ethe
    的头像 发表于 04-16 13:32 1564次阅读
    EtherCAT 主站开发,国内工程师<b class='flag-5'>最常</b>问的<b class='flag-5'>三个</b>核心问题

    Linux新手最常踩的10命令坑介绍

    最新的Linux内核特性(kernel 6.x系列)和常见发行版环境(Ubuntu 24.04 LTS、RHEL 9.4、CentOS Stream 10),系统梳理新手最常踩的10命令坑,帮助读者建立正确的操作习惯和风险意识
    的头像 发表于 04-09 10:11 289次阅读

    SPE协议芯片如何让工业布线瘦身70%?三个实战案例告诉你

    在工业现场,布线一直是让人头疼的问题。传统的以太网需要4对线,体积大、成本高;现场总线又速率低、互操作性差。SPE(单对以太网)协议芯片的出现,正在改变这一切。本文通过三个实战案例,看看SPE如何让工业布线瘦身70%。
    的头像 发表于 03-13 17:49 1263次阅读

    导热系数越高越好?关于导热硅胶片的三个认知误区

    。本文将揭示三个最常见的认知偏差,帮助您做出更明智的选择。 误区一:导热系数越高,散热效果就一定越好 这可能是最具迷惑性的误区。理论上,导热系数越高,材料传导热量的能力越强。然而在实际应用中,散热
    发表于 03-12 13:49

    骏马奔腾,芯向未来:SiC功率器件的“三个必然”与丙午马年的产业跃迁

    骏马奔腾,芯向未来:SiC功率器件的“三个必然”与丙午马年的产业跃迁 日期: 2026年 丙午马年 除夕 主题: 倾佳电子杨茜“三个必然”战略论断与基本半导体碳化硅技术的产业替代逻辑 关键词
    的头像 发表于 02-15 10:33 197次阅读
    骏马奔腾,芯向未来:SiC功率器件的“<b class='flag-5'>三个</b>必然”与丙午马年的产业跃迁

    altium designer 如何画短路两或者三个网络的封装?

    如何我画了一天线,有3引脚,TX1,TX2,GND, 但实际上这三个引脚是连在一起的。我导入pcb后,会报DRC警告,这个该怎么解决?
    发表于 02-12 19:30

    三个经典开关电源实际问题解析

    下面三个关于多路输出电源连续工作模式的问题,测试一下您的电源设计知识。然后核对您的答案。
    的头像 发表于 01-22 16:08 4096次阅读
    <b class='flag-5'>三个</b>经典开关电源实际问题解析

    MDD从工程故障看极管三个极的设计误区与失效案例

    一、为什么极管问题总是“看起来很随机”?在FAE现场支持中,经常遇到如下问题:-同一电路,有的板子正常,有的异常-高温下工作不稳定-更换批次后性能漂移这些问题,90%都与三个极的设计与使用方式有关
    的头像 发表于 01-19 11:48 447次阅读
    MDD从工程故障看<b class='flag-5'>三</b>极管<b class='flag-5'>三个</b>极的设计误区与失效案例

    防漆应用失败?八常见问题与解决方案一文搞定 | 东莞 铬锐特实业

    东莞防漆|铬锐特实业官网 | 防漆涂覆失败怎么办?本文总结8最常见问题(如起泡、不均匀、发白、附着力差等)及实用解决方案,一文帮您避开
    的头像 发表于 12-24 00:36 805次阅读
    <b class='flag-5'>三</b>防漆应用失败?八<b class='flag-5'>个</b><b class='flag-5'>常见</b>问题与解决方案一文搞定 | 东莞 铬锐特实业

    #define预编译的指令

    #define预编译指令 顾名思义,这个指令的含义是“定义”,大家可以把该指令视为一种文本的替换。详细在下面代码展示 [list=1] [*]//使用该指令定义了一数 [*]#define
    发表于 12-05 07:29

    #include预编译的指令

    众所周知#include“xxx.h”的作用是用来包含头文件的,作用是能够调用头文件中的各类枚举/结构体/函数定义等。那么一C文件是如何通过#include“xxx.h”文件就能编译到那些定义呢
    发表于 12-04 07:43

    未来工业AI发展的三个必然阶段

    与优化 能力的深层革命。 未来十年,工业AI的发展将经历三个清晰的阶段:  智能辅助 → 智能决策 → 自主优化 。这次进化,构成了工业从“人控机器”到“机器共智”的核心路径。 一、第一阶段:智能辅助(AI for Assistance) 时间窗口:
    的头像 发表于 10-27 15:47 674次阅读
    未来工业AI发展的<b class='flag-5'>三个</b>必然阶段

    请问K230D的三个相机能同步采样吗?

    如题 K230D的三个相机能同步采样吗?
    发表于 08-04 06:32

    怎么结合嵌入式,Linux,和FPGA三个方向达到一均衡发展?

    在嵌入式领域,不少人都怀揣着让嵌入式、Linux 和 FPGA 三个方向实现均衡发展的梦想,然而实践中却面临诸多挑战。就像备受瞩目的全栈工程师稚晖君,他从大学玩单片机起步,凭借将智能算法融入嵌入式而
    的头像 发表于 06-25 10:08 1092次阅读
    怎么结合嵌入式,Linux,和FPGA<b class='flag-5'>三个</b>方向达到一<b class='flag-5'>个</b>均衡发展?