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

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

3天内不再提示

预编译的理解及作用原理

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-12-29 17:07 次阅读
poYBAGOtWAqAR7InAAEgB0IqMEU843.png

三种预处理详解
1、宏定义指令

宏定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。
宏最常见的用法是定义代表某个值的全局符号;而第二种用法是定义带参数的宏(宏函数),这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。
#define指令:
#define预处理指令用来定义宏。该指令最简单的格式是:声明一个标识符,给出这个标识符代表的代码(比如像圆周率这样的数)。在后面的源代码中,我们就可以使用定义的宏取代要使用的代码,代码举例:

#define PI 3.141592654

使用宏的好处有两点:
一是使用方便。如下:

#define PI 3.1415926

PI显然比3.1415926写着方便。
二是定义的宏有了意义,可读性强。如例1,MAX_NUM,望文生意便知是最大数量的意思,比单纯使用10这个数字可读性要强的多。
三是容易修改。如例1,如果在程序中有几十次会使用到MAX_NUM,修改只需要在宏定义里面修改一次就可以,否则你会修改到崩溃。
2、条件编译指令
程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。条件编译指令将决定哪些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。
#if/#endif/#else/#elif指令:
#if指令检测跟在制造另关键字后的常量表达式。如果表达式为真,则编译后面的代码,直到出现#else、#elif或#endif为止;否则就不编译。
#endif用于终止#if预处理指令。
#else指令用于某个#if指令之后,当前面的
#if指令的条件不为真时,就编译
#else后面的代码。
代码举例:

#define DEBUG       //此时#ifdef DEBUG为真
//#define DEBUG 0  //此时为假
int main()
{
  #ifdef DEBUG
     printf("Debuggingn");
  #else
     printf("Not debuggingn");
  #endif
  printf("Runningn");
  return 0;
}  

这样我们就可以实现debug功能,每次要输出调试信息前,只需要#ifdef DEBUG判断一次。不需要了就在文件开始定义#define DEBUG 0
#elif预处理指令综合了#else和#if指令的作用。

3、头文件包含指令
采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条#include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。
#include预处理指令的作用是在指令处展开被包含的文件。包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。标准C编译器至少支持八重嵌套包含。预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含,这个的处理办法上面已经给出。
在程序中包含头文件有两种格式:

#include 
#include "my.h"

第一种方法是用尖括号把头文件括起来。这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。
第二种方法是用双引号把头文件括起来。这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件,如果找不到,再搜索编译器自带的头文件。
采用两种不同包含格式的理由在于,编译器是安装在公共子目录下的,而被编译的应用程序是在它们自己的私有子目录下的。一个应用程序既包含编译器提供的公共头文件,也包含自定义的私有头文件。采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。
预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。

审核编辑:汤梓红

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

    关注

    180

    文章

    7530

    浏览量

    128763
  • 编译
    +关注

    关注

    0

    文章

    615

    浏览量

    32396
  • 预处理
    +关注

    关注

    0

    文章

    32

    浏览量

    10411
  • 宏定义
    +关注

    关注

    0

    文章

    48

    浏览量

    8927
收藏 人收藏

    评论

    相关推荐

    请问有文档描述ZigBee预编译宏定义含义吗?

    TI ZigBee 技术牛人:你好!请问有文档描述了Texas Instruments\Z-Stack Home 1.2.0中预编译宏定义详细解释吗?
    发表于 08-13 07:51

    未能获得预编译的模拟库信息

    14.4)---------------------------警告:无法获得预编译的模拟库信息。要解决此问题,您可以执行以下任一操作: - 如果库已经预编译,请使用以下方法之一指向它们:*将
    发表于 03-17 10:17

    请问C语言内宏定义是被预编译器处理吗?

    C语言内宏定义是被预编译器处理还是被编译器处理
    发表于 03-20 04:35

    什么是预编译

    1 预编译预编译又称为预处理 ,处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。...
    发表于 07-15 06:03

    Verilog 预编译

    Verilog 预编译Verilog 语言支持宏定义(`define),参数 parameter,局域参数(localparam)以及`include等内容。这些数据常量的支持极大方便数字系统
    发表于 08-11 09:31

    什么是预编译?什么时候使用预编译

    什么是预编译?什么时候使用预编译呢?
    发表于 02-25 07:43

    yolov5预编译后结果异常

    转为预编译版本后,在rv1126板子上推理结果异常,完全不相同,又遇到相同问题的大佬可以分享下如何解决吗?
    发表于 03-16 19:16

    X-CUBE-IOTA v1.2.0预编译版不起作用的原因?如何解决?

    我试图将我的项目更新到 1.2.0 版本,但没有成功。我现在还发现 stm32f4 的预编译版本不起作用。另外,如果我自己编译它也行不通。我通过 dhcp 获得了一个有效的 ip,但该 ip 立即
    发表于 01-16 06:11

    编译器如何处理使用预编译库SMING文件编译的应用程序中未使用的库?

    预编译的库文件,由位于顶部的应用程序使用。 编译器如何处理使用预编译库SMING文件编译的应用程序中未使用的库?即使未使用,库也会消耗 RAM 和闪存吗?是否应该删除这些未使用的库以节
    发表于 06-12 08:54

    C语言编译器常见的预编译指令详细资料说明

    编译器对C程序的处理可以明确地分为两步。第一步由预编译器完成。以#开头的预编译指令可能会影响编译器设置或者进行文本替换。注意,预编译器变量(
    发表于 06-05 17:52 2次下载
    C语言<b class='flag-5'>编译</b>器常见的<b class='flag-5'>预编译</b>指令详细资料说明

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

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

    C语言中常见预编译指令的灵活秒用

    有时候出于对程序代码优化的考虑。希望只对其中一部分内容进行编译。此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。 常见的
    的头像 发表于 04-27 11:18 1365次阅读

    浅谈预编译指令常见用法

    很多优秀的代码,都会借用预编译指令来完善代码,今天就来讲讲关于预编译指令的内容。 常见的预处理指令如下: #指令,无任何效果 #include含一个源代码文件 #define义宏 #undef消已定
    的头像 发表于 06-23 17:30 1391次阅读
    浅谈<b class='flag-5'>预编译</b>指令常见用法

    什么是预编译

    预编译就是处理以#开头的指令,比如赋值#include包含的文件、#define宏定义的替换、条件编译等。预编译就是为编译前做准备工作的阶段,主要处理以#开头的
    发表于 01-13 13:52 0次下载
    什么是<b class='flag-5'>预编译</b>

    【Linux编程】如何使用gcc生成预编译文件?

    【Linux编程】如何使用gcc生成预编译文件?
    的头像 发表于 08-31 13:07 1572次阅读
    【Linux编程】如何使用gcc生成<b class='flag-5'>预编译</b>文件?