预处理指令用法详解(C语言)
前言
使编译器执行预处理操作的代码被称为预处理指令,本文介绍常见的预处理指令的实际用法。
(资料图片)
一、预处理符号
预处理符号是C语言内置的符号,是可以直接使用的。
其中,若遵顼ANSI C,则__STDC__
为1,否则未定义。
二、#define
1)定义标识符
#define可以用来定义标识符,其语法为:#define name stuff
,经过预处理后,stuff
会被直接替换为·name
。
若stuff
的内若过长,可在句末加上\
续行符号,像这样:
#include#define Piccaso "Pablo,Diego,José\Francisco,de,Paula,Juan,Nepomuceno\,María,de,los,Remedios,Cipriano,de\,la,Santísima,Trinidad,Ruiz,y,Picasso"int main(){printf("%s", Piccaso);return 0;}
示例1:数值替换
int main(){int a = 100;return 0;}
示例2:循环替换
#includeint main(){while(1){printf("A");}return 0;}
运行代码,将会在屏幕上死循环地打印A
。
示例3:分支替换
int main(){int input = 0;switch (input){case 1:break; case 2:break; case 3:}return 0;}
2)宏定义
#define允许有参数的文本替换,这种操作通常称为宏,其语法为:#define name(list) stuff
,其中,list
是由逗号隔开的符号表,符号有可能出现在stuff
中。
示例1:
int main(){printf("%d", 5+5);return 0;}
示例2:
int main(){printf("%d", 10*double(5+1));return 0;}
因为#define
的功能只是替换,若要利用宏定义实现快捷的函数操作,最好的方法是在宏定义时多加括号,以便于达到整体求值的效果,像这样:#define double(x) (x)+(x)
。
注意:由于宏是直接替换,因此传参时严禁使用自增,自减,传参时使用,替换后依然会再次执行,会导致不可预测的后果。
3)字符串转换符
字符串有自动连接的特点,例如运行以下这段代码:
#includeint main(){printf("123" "456");return 0;}
效果图:
字符串转换符#就是利用这个特性,它可以将宏定义中传入的参数,替换为字符串格式。
#include#define sum(x) printf("the val of "#x" is %d",x)int main(){int a = 10;sum(a);return 0;}
在上述代码中,#号
将a
直接转化为字符串,随后三个字符串拼接在一起。
效果图:
利用该方法可以只传参一次实现值和名
同时打印。
4)片段链接符
在宏定义时,片段连接符##
可以实现将两个符号连接在一起,使其成为一个符号,前提是这个合成的符号必须已经被定义。
#include#define double(x) sum##x*=2int main(){int sum1 = 1;int sum2 = 1;int sum3 = 1;double(1);printf("%d %d %d", sum1, sum2, sum3);return 0;}
在上述代码中,##
会把sum和参数x连接在一起,当我们传入1经过预处理后,等效于:sum1*=2
。
效果图:
5)宏定义VS函数
宏定义的优势:
宏定义的执行速度远远超过函数,当执行简单的计算时,更适合使用宏定义。宏定义传参时没有类型检测,可以将任意的数据传入。宏定义是直接替换,可以传入各种各样的符号,实现许许多多函数做不到的功能。(可以传入类型、传入函数、传入语句等等)宏定义的劣势:
宏定义不能调试、不能递归,因此宏定义只适合做简单的计算。宏定义是直接替换,因此相邻操作符的优先级很有可能产生不期望的顺序,因此要尽可能带括号。宏定义传参没有类型检测,因此不够严谨。6)命名公约
以下几条公约,必须遵守
宏定义的名必须全部大写。函数名不可以全部大写。三、#undef#undef
宏定义删除,可以在函数内部使用!被删除后的标识就不能再使用了。
四、命令行编译
指在VScode
或Linux
等用命令行执行编译的环境下,可以在编译时对变量进行赋值。
五、条件编译
在写程序时,有些代码是为了查看某个部分是否正确而写的的调试代码。
删除很可惜,但又不想让其编译,此时就可以使用选择性编译
。
但实质上使用if
语句或直接注释
会更加方便,但在C语言内置的头文件中,为了节约时间经常使用条件编译。
1)常量表达式判断
#if 常量表达式//...#endif
常量表达式为真,则中间的语句编译;
常量表达式为假,则中间的语句不编译。
此外,也可以写成多分支的表达式条件编译。
int main(){#if 0printf("111");#elif 1printf("222");#else 0printf("333");#endifreturn 0;}
效果图:
2)是否定义判断
判断某个符号是否被定义,只要被定义,就编译中间的语句,无论其被定义为什么。
#include#define MAXint main(){#if defined(MAX)//或#ifdef MAXprintf("111");#endifreturn 0;}
或判断某个符号是否没定义,没定义则编译。
#include#define MAXint main(){#if !defined(MAX)//或#ifndef MAXprintf("111");#endifreturn 0;}
3)嵌套判断
条件编译是可以互相嵌套的。
#include#define DEBUG int main(){#ifdef DEBUG#if 1printf("111");#elif 0printf("222");#endif#endif return 0;}
如上述代码是在是否定义判断中嵌套常量表达式判断。
效果图:
六、头文件的包含
1)双引号与尖括号
对于#include
来说,后面的文件有两种引用方法:
所有的头文件在包含时都可以使用双引号,但为了速度和区别位置,建议自己写的头文件用双引号,标准库中的用尖括号。
2)头文件的嵌套包含
可以将许许多多的头文件都包含在一个自己创建的头文件中,最后只需要在其他的源文件中包含该自己创建的头文件即可,像这样:
3)头文件重复包含解决方法
在写多人合作的大型项目时,每个程序员可能都要包含一次公用的头文件,当他们写的代码汇总时,这个头文件可能会被包含多次。
因此,我们使用条件编译来解决这个问题。
#if !defined(TIME)#define TIME //...//... //在这里实现各种函数//...#endif
假设上述代码为head.h
,当我们第一次包含head.h
时,由于TIME没有被定义,因此会定义一个TIME,同时编译里面的函数。
当我们第二次包含head.h
时,因为TIME被定义过了,即使head.h
里面的内容被拷贝到源文件中,也不会进行编译,从而加快了速度。
注意:在头文件开头加入#pragma once
即可一键实现上述效果,不必冗杂的代码,但仅限于自己写的头文件,标准库的头文件已经帮你加完了。
感谢您的阅读与耐心~
标签: 编程算法

加快场景创新 科技部首批支持建设十个人工智能示范应用场景
2022-08-16

科技部公布《企业技术创新能力提升行动方案》 亮出10项行动内容
2022-08-16

进入了发展快车道 冷链行业市场规模正在快速膨胀
2022-03-21

行业正站在风口 数字化时代在为传统的自行车产业赋能
2022-03-21

以做强实体经济支撑为重点 成都单个项目年度计划投资同比提升
2022-03-21

拥有多个国际赛事的直播版权 广州游戏电竞企业业绩向好
2022-03-21

投诉量激增 直播带货存在这么多问题的主要原因是什么?
2022-03-21

工作专班深入到各企业 春寒料峭挡不住松原市施工热情
2022-03-21

引导企业向提供“产品+服务”转变 湖南加快智能农机服务化转型
2022-03-21

创新平台建设和科技成果转化 德州加大力度重奖创新
2022-03-21
科技部公布《企业技术创新能力提升行动方案》 亮出10项行动内容
进入了发展快车道 冷链行业市场规模正在快速膨胀
行业正站在风口 数字化时代在为传统的自行车产业赋能
以做强实体经济支撑为重点 成都单个项目年度计划投资同比提升
拥有多个国际赛事的直播版权 广州游戏电竞企业业绩向好
投诉量激增 直播带货存在这么多问题的主要原因是什么?
工作专班深入到各企业 春寒料峭挡不住松原市施工热情
引导企业向提供“产品+服务”转变 湖南加快智能农机服务化转型
创新平台建设和科技成果转化 德州加大力度重奖创新
潜在风险进一步放大 商品房现房销售已是大势所趋
有序复工复产 1—2月份工业经济发展新动能持续增强
多层次高频调度 1至2月河北省工业运行先行指标稳中有增
以车路协同为基础 智能交通推动城市交通绿色高质量发展
人才短板成为制约产业链高质量发展的关键节点
通过技术手段整合调配供给资源 家政行业不断提质扩容
强化产业链深层次合作 加强重大装备国产化“一条龙”模式构建
如何进一步提升纳税人缴费人的减税降费获得感?
探索建设大数据及网络安全示范试点城市有哪些积极意义?
对制造业中小微企业实施缓缴税费政策有哪些积极意义?
进一步增强自我保护意识 消费者需注意辨别谨慎消费
将“走出去”变“请进来” 西安贸易产业转移承接作用不断得到增强
厦门应如何融入“数字中国”的重大战略发展大局?
江苏省如何不断满足老人日益增长的养老服务需求?
建设一体化的职业健康信息管理平台 天津职业人群保障加强
潜力持续释放 1—2月乡村消费品市场恢复略好于城镇
直接对接社会化服务 楼宇调解室将整体提升青岛劳动争议水平
成功化解纠纷11.47万件 银保监会服务质量日趋提高
春雷响百虫出 惊蛰文化在其他方面有了进一步发展
青绿山水画在古代山水画发展史上有着怎样的影响与地位?


- 开播即爆款 “文化类节目收视率低”这一固有印象被推翻
- 涵盖了109件真迹作品 凯斯·哈林展览将持续至6月13日
- 带有一点自信的自嘲 “隔路”是另一种味道的“凡尔赛”
- 与文渊阁前后呼应 “何以中国”特展隆重致敬文化大成
- 严重者可造成暂时性失明 享受冰雪运动要注意眼睛的健康防护
- 种类繁多让人眼花缭乱 选购牛奶时需要重点关注什么?
- 网课让孩子感到不安焦虑怎么办?八问八答回应广大家长关切
- 循环系统很容易受到刺激 “倒春寒”期间老人该如何做?
- 青少年患者睡眠问题日趋增加 9条建议为孩子助眠
- 我国肥胖人群正逐年递增 不良饮食习惯是重要诱因
- 如何减少噪声对听力的损伤?这份耳部和听力保健小贴士请收好
- 强化住房限购措施 西安限购限售范围进一步扩大
- 多种方式增加供给 进一步降低新市民和青年人的居住成本
- 预计9月下旬海口可实现安居房申请网上办理
- 政策调控力度持续升级 8月百城二手房市场均价止涨转跌
- 8月中国新房找房热度依然保持平稳 环比微涨0.2%
- 进一步加强商品房销售价格备案管理 今年全国楼市调控刷新历史纪录
- 西安第二批集中供地中28宗为现场拍卖方式出让
- 细分化需求得到释放 房屋居住的属性越发凸显
- 佛山顺德龙江近日挂牌商住地起拍价约19.88亿元
- 青岛市4宗地竞品质抽签结果出炉 地溢价均约15%
- 坚持政策支持、多方参与 浙江版保障性租赁住房明确新增比例目标
- 简化审批流程 武汉将实现房源申请配租全程网上办
- 哈尔滨新增本土确诊病例3例 活动轨迹公布
- 哈尔滨市公布3例新增本土新冠肺炎确诊病例活动轨迹
- 山东深耕文化资源 推动旅游业高质量发展
- 今年新增952件(套)!南京大屠杀再添新证
- 四川非遗传承人张雄志:巧手捏面塑 指尖传非遗
- 10月以来我国寒潮为何如此频繁?中国气象局回应
- 56位残疾人士登上黄山 互利互勉共建生活希望
- 安徽潜山两车相撞 已致8人死亡3人受伤
- 上海洋山海关首次在出口货运渠道查获夹带卷烟
- 山西忻州古城:一城风华延续千年历史文脉
- 呼伦贝尔新巴尔虎右旗公布1例无症状感染者行动轨迹
- 新增“53+1” 内蒙古累计本土确诊病例增至185例
- 昆明公安打击破坏生物多样性犯罪 抓获130名涉案嫌疑人
- 山西朔州“11·11”较大透水事故调查报告发布 对38人问责处理
- “海关国门小卫士”竞争上岗 淘汰率接近一半
- 深圳摧毁特大品牌化妆品走私网
- 28人被问责!山西石港煤业“3·25”事故调查报告公布
- 湖南韶山以河长制带动全民治水 让每一处水面“长治久清”
- 上海市奉贤区人大常委会原党组书记袁晓林被“双开”
- 民进会员谈反映社情民意信息工作:心怀大我 敢讲实情
- 80岁“留守”奶奶短视频诉孤独 千万网友心疼:我们陪您唠嗑
- 40年来为子弟兵送出1.3万余双布鞋和鞋垫的“布鞋奶奶”走了
- 当男幼师是什么体验?他们说:有委屈尴尬 但大部分是幸福
- 庐阳警方通报幼童坠亡事件:嫌疑人已被刑拘
- 内蒙古新增本土确诊病例53例、本土无症状感染者1例
- 哈尔滨市启动部分地区第一轮全员核酸检测
- 四川通江发生两车相撞事故 致3人死亡