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

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

3天内不再提示

浅谈预编译指令常见用法

strongerHuang 来源:小麦大叔 作者:小麦大叔 2021-06-23 17:30 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

很多优秀的代码,都会借用预编译指令来完善代码,今天就来讲讲关于预编译指令的内容。

常见的预处理指令如下:

#指令,无任何效果

#include含一个源代码文件

#define义宏

#undef消已定义的宏

#if果给定条件为真,则编译下面代码

#ifdef果宏已经定义,则编译下面代码

#ifndef果宏没有定义,则编译下面代码

#elif果前面的if定条件不为真,当前条件为真,则编译下面代码

#endif束一个if……#else件编译块

#error止编译并显示错误信息

本来只是想了解一下#ifdef,#ifndef,#endif的,没想到查出来这么多的预处理指令,上面的多数都是常见的,但是平时没有怎么注意预处理这方面的内容,所以这里梳理一下知识吧。

同时有什么不妥的地方,或者遗漏了什么内容,还请留言指出。

什么是预处理指令?

预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
预处理指令是在编译器进行编译之前进行的操作,对其进行初步的转换,产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理。在很多编程语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码(防止重复包含某些文件)。
要完成这些工作,就需要使用预处理程序。尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。预处理过程还会删除程序中的注释和多余的空白字符。#include包含一个源代码文件这个预处理指令,我想是见得最多的一个,简单说一下;

第一种方法是用尖括号把头文件括起来。

#include 《stdio.h》

这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。

第二种方法是用双引号把头文件括起来。

#include “test.h”

这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件,如果找不到,再搜索编译器自带的头文件。采用两种不同包含格式的理由在于,编译器是安装在公共子目录下的,而被编译的应用程序是在它们自己的私有子目录下的。
一个应用程序既包含编译器提供的公共头文件,也包含自定义的私有头文件。采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。#define定义宏有关#define这个宏定义,在C语言中使用的很多,因为#define存在一些不足,C++强调使用const来定义常量。宏定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。记住仅仅是进行标识符的替换。下面列举一些#define的使用:

用#define实现求最大值和最小值的宏

#include 《stdio.h》

#define MAX(x,y) (((x)》(y))?(x):(y))

#define MIN(x,y) (((x)《(y))?(x):(y))

int main(void)

{

#ifdef MAX //判断这个宏是否被定义

printf(“3 and 5 the max is:%d

”,MAX(3,5));

#endif

#ifdef MIN

printf(“3 and 5 the min is:%d

”,MIN(3,5));

#endif

return 0;

}

/*

* (1)三元运算符要比if,else效率高

* (2)宏的使用一定要细心,需要把参数小心的用括号括起来,

* 因为宏只是简单的文本替换,不注意,容易引起歧义错误。

*/

宏定义的错误使用

#include 《stdio.h》#define SQR(x) (x*x)int main(void)

{

int b=3;

#ifdef SQR//只需要宏名就可以了,不需要参数,有参数的话会警告

printf(“a = %d

”,SQR(b+2));

#endif

return 0;

}

/*

*首先说明,这个宏的定义是错误的。并没有实现程序中的B+2的平方

* 预处理的时候,替换成如下的结果:b+2*b+2

* 正确的宏定义应该是:#define SQR(x) ((x)*(x))

* 所以,尽量使用小括号,将参数括起来。

*/

宏参数的连接

#include 《stdio.h》#define STR(s) #s#define CONS(a,b) (int)(a##e##b)int main(void)

{

#ifdef STR

printf(STR(VCK));

#endif#ifdef CONS

printf(“

%d

”,CONS(2,3));

#endif

return 0;

}

/* (绝大多数是使用不到这些的,使用到的话,查看手册就可以了)

* 第一个宏,用#把参数转化为一个字符串

* 第二个宏,用##把2个宏参数粘合在一起,及aeb,2e3也就是2000

*/

用宏得到一个字的高位或低位的字节

#include 《stdio.h》#define WORD_LO(xxx) ((byte)((word)(xxx) & 255))#define WORD_HI(xxx) ((byte)((word)(xxx) 》》 8))int main(void)

{

return 0;

}

/*

* 一个字2个字节,获得低字节(低8位),与255(0000,0000,1111,1111)按位相与

* 获得高字节(高8位),右移8位即可。

*/

用宏定义得到一个数组所含元素的个数

#include 《stdio.h》#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))int main(void)

{

int array[100];

#ifdef ARR_SIZE

printf(“array has %d items.

”,ARR_SIZE(array));

#endif

return 0;

}

/*

*总的大小除以每个类型的大小

*/

关于#define宏的使用,应该特别小心,尤其是含有参数计算的时候如下2示例,最保险的做法将参数用括号括起来。#ifdef,#ifndef,#endif.。。的使用以上这些预编译指令,都是条件编译指令,也就是说,将决定那些代码被编译,而哪些不被编译。

示例1:

#include 《stdio.h》#include 《stdlib.h》#define DEBUGint main(void)

{

int i = 0;

char c;

while(1)

{

i++;

c = getchar();

if(‘

’ != c)

{

getchar();

}

if(‘q’ == c || ‘Q’ == c)

{

#ifdef DEBUG//判断DEBUG是否被定义了

printf(“We get:%c,about to exit.

”,c);

#endif

break;

}

else

{

printf(“i = %d”,i);

#ifdef DEBUG

printf(“,we get:%c”,c);

#endif

printf(“

”);

}

}

printf(“Hello World!

”);

return 0;

}

/*#endif用于终止#if预处理指令。*/

ifdef 和 #ifndef

#include 《stdio.h》#define DEBUG

main()

{

#ifdef DEBUG

printf(“yes ”);

#endif#ifndef DEBUG

printf(“no ”);

#endif

}

//#ifdefined等价于#ifdef;//#if!defined等价于#ifndef

#else指令

#elif指令

其他一些指令

#error指令将使编译器显示一条错误信息,然后停止编译。

#line指令可以改变编译器用来指出警告和错误信息的文件号和行号。

#pragma令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。

编辑:jq

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

    关注

    22

    文章

    2122

    浏览量

    76695
  • 代码
    +关注

    关注

    30

    文章

    4940

    浏览量

    73116
  • 编译器
    +关注

    关注

    1

    文章

    1669

    浏览量

    51069
  • 编译
    +关注

    关注

    0

    文章

    687

    浏览量

    34935

原文标题:预编译指令常见用法

文章出处:【微信号:strongerHuang,微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    #define预编译指令

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

    #include预编译指令

    ?那就要从编译器眼中的#include指令说起。 长话短说,大家可以把#include“xxx.h”看成是文本的展开,简而言之就是通过该指令把h文件里的内容进行了展开。如下范例所示,我们定义一个H文件
    发表于 12-04 07:43

    使用Vivado 2018.2编译E203的mcs文件,遇到的问题求解

    Hi 各位,我在尝试使用Vivado 2018.2编译E203的mcs文件,遇到如下两个问题: 1. 按照书中步骤运行,执行完make mcs之后得到的mcs文件与git中预编译出来的mcs文件有
    发表于 11-11 06:04

    请问蜂鸟自带编译工具怎么才能不使用压缩指令呢?

    请问,benchmark里编译选项应该如何设置才能把压缩指令去掉,保留完整的32位指令呢?我尝试修改编译选项,将-march=rv32imafdc修改为-march=rv32imafd
    发表于 11-07 07:52

    通过内联汇编调用乘法指令mulh\\mulhsu\\mulhu

    高32位 mulhsurd, rs1,rs2 将rs1当作有符号数,rs2当作无符号数相乘,取高32位 2.由于C语言中的乘法符号,在经过软件编译后生成的汇编指令位mul指令,因此,想要验证
    发表于 10-24 06:52

    env工具显示指令不是内部指令是怎么回事?

    Rt-thread studio软件能正常使用,为什么官网下载Env软件打开Bsp路径下对程序进行编译显示不是内部指令.
    发表于 10-10 07:55

    步进电机控制指令详解

    这些指令主要是针对用 PLC 直接联动伺服放大器,目的是可以不借助其他扩展设备(例如1GM 模块)来进行简单的点位控制, 使用这些指令时最好配合三菱的伺服放大器 (如 MR-J2)。然而,我们也可以用这些指令来控制步进电机的运行
    的头像 发表于 06-12 10:33 1583次阅读
    步进电机控制<b class='flag-5'>指令</b>详解

    飞凌嵌入式ElfBoard ELF 1板卡-uboot编译原理介绍

    编译工具将源码文件编译成可执行文件的过程并不是一步到位的,其中要经过一个类似工厂流水线的过程,交叉编译工具中包含负责处理各个环节的功能工具,所以叫做交叉编译工具链。
    发表于 05-22 11:17

    浅谈压力变送器的常见故障及解决措施

    压力变送器在工业自动化领域中扮演着至关重要的角色,然而,由于其工作环境的复杂性和多样性,故障时有发生。以下是对压力变送器常见故障及解决措施的浅谈: 一、变送器无输出 ● 常见故障现象: 变送器在接通
    的头像 发表于 04-23 17:18 1756次阅读

    浅谈电磁流量计的常见故障及排除方法

    电磁流量计作为常用的流量测量仪表,在使用过程中可能会遇到各种故障。以下是对电磁流量计常见故障及排除方法的浅谈: 一、仪表显示最小或无显示 当电磁流量计显示最小或无显示时,通常意味着传感器没有流量信号
    的头像 发表于 04-20 17:56 1289次阅读

    Triton编译器如何提升编程效率

    开发者能够更快地开发出更高效的软件。 1. 代码优化 1.1 编译时优化 Triton 编译器在编译时进行了大量的代码优化。这些优化包括但不限于: 指令选择 :Triton
    的头像 发表于 12-25 09:12 1186次阅读

    Triton编译器的优化技巧

    在现代计算环境中,编译器的性能对于软件的运行效率至关重要。Triton 编译器作为一个先进的编译器框架,提供了一系列的优化技术,以确保生成的代码既高效又适应不同的硬件架构。 1. 指令
    的头像 发表于 12-25 09:09 1807次阅读

    Triton编译器的常见问题解决方案

    Triton编译器作为一款专注于深度学习的高性能GPU编程工具,在使用过程中可能会遇到一些常见问题。以下是一些常见问题的解决方案: 一、安装与依赖问题 检查Python版本 Triton编译
    的头像 发表于 12-24 18:04 6369次阅读

    Triton编译器与其他编译器的比较

    Triton编译器与其他编译器的比较主要体现在以下几个方面: 一、定位与目标 Triton编译器 : 定位:专注于深度学习中最核心、最耗时的张量运算的优化。 目标:提供一个高度抽象、灵活、高效
    的头像 发表于 12-24 17:25 1571次阅读

    Triton编译器功能介绍 Triton编译器使用教程

    Triton 是一个开源的编译器前端,它支持多种编程语言,包括 C、C++、Fortran 和 Ada。Triton 旨在提供一个可扩展和可定制的编译器框架,允许开发者添加新的编程语言特性和优化技术
    的头像 发表于 12-24 17:23 2667次阅读