电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

c 预处理 指令和c宏

9页
  • 卖家[上传人]:小**
  • 文档编号:89123292
  • 上传时间:2019-05-18
  • 文档格式:DOC
  • 文档大小:25KB
  • / 9 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 1、C 预处理指令和C宏C预处理指令和C宏C语言程序在被编译成可执行文件时,也许你使用的IDE只需点击一下编译按钮,或者使用gcc编译器的,也是一条命令就完成了(当然使用命令时,会有些必须的参数)。但是真正实际情况,这个过程需要经历:预处理-编译-链接-装载。当然我们的编译器已经高度发达,将这些内容全部实现了。而预处理最长被我们使用一条指令是#include。我们用它来加载头文件。同时还会有些使用预处理指令的C宏或是编译条件等。一:首先先将C语言所有预处理指令简单介绍一下:1.#define指令:该条指令最常被用来定义符号常量或明显的常量,当然定一个类函数宏也是需要使用它的。每个#define行由三部分组成,第一部分是指令自身#define,第二部分是所选择的缩略语,这些缩略语称为宏(macro)。第三部分为宏替换的主体(或列表)。举例如下:#definePXprintf(xis%dn,x)#definePXprintf(xis%dn,x)预处理指令宏主体(替换列表)其中对于第二部分(宏)有如下要求:宏的名字中不能有空格,而且必须遵循C变量命名规则:只能使用字母、数字和下划线(_)而且第一

      2、个字符不能为数字。同时要注意,对于所有预处理指令都是从开始到第一个换行符结束。#define指令的作用范围是从出现位置开始到文件结束。预处理器在处理时,将源文件中出现的宏用其主体做替换。而且这种替换是可嵌套的。这种嵌套替换举例如下:#defineTWO2#defineFOURTWO*TWO则FOUR将被做如下处理:第一次替换后变为:TWO*TWO,再次替换后变为2*2。在const关键字得到C的支持后,又提供了一种创建常量的灵活方法。使用const可以创建全局常量和局部常量、数字常量、数组常量和结构常量。对使用#define定义的符号常量可以被用来指定标准数组的大小,与const的简单举例类比。#defineLIMIT20constintLIM=50;staticintdata1LIMIT;/合法staticintdata2LIM;/无效constintLIM2=2*LIMIT;/合法constintLIM3=2*LIM;/无效在#define中使用参数。通过使用参数可以创建外形和作用都与函数相似的类函数宏。宏的参数也用圆括号括起来。举例如下:#defineMEANX,Y预处理指令宏(

      3、X和Y为宏的参数)替换主体带参数的宏外形与函数非常相似,但是在使用时与真正的函数调用不完全相同。如果不能理解替换这种预处理形式很有可能出现意料之外的错误。见如下例子程序:/*mac_arg.c-macroswitharguments*/#includestdio.h#defineSQUARE(X)X*X#definePR(X)printf(Theresultis%d.n,X)intmain(void)intx=4;intz;printf(x=%dn,x);z=SQUARE(x);printf(EvaluatingSQUARE(x):);PR(z);z=SQUARE(2);printf(EvaluatingSQUARE(2):);PR(z);printf(EvaluatingSQUARE(x+2):);PR(SQUARE(x+2);printf(Evaluating100/SQUARE(2):);PR(100/SQUARE(2);printf(xis%d.n,x);printf(EvaluatingSQUARE(+x):);PR(SQUARE(+x);printf(Afterincrem

      4、enting,xis%x.n,x);return0;使用gcc4.3.2编译后输出的结果如下:(在不同的编译器出现的结果可能不同)x=4EvaluatingSQUARE(x):Theresultis16.EvaluatingSQUARE(2):Theresultis4.EvaluatingSQUARE(x+2):Theresultis14.Evaluating100/SQUARE(2):Theresultis100.xis4.EvaluatingSQUARE(+x):Theresultis36.Afterincrementing,xis6.前两项的结果正确的但是接下来的则有些出乎意外。PR(SQUARE(x+2);时x值为4,那么x+2的SQUARE(x+2)时应该是6*6结果应该为36。而程序运行的结果则是14.如果你使用替换原则将SQUARE(x+2)替换则变为x+2*x+2这时x=4则计算结果正是14.要处理这种情况(优先级问题),可以采用对替换主题加圆括号保证优先级。最好参数本身也使用括号,保证优先级正确性。修改如下:#defineSQUARE(X)X*X之后的情况类似。特别指

      5、出:EvaluatingSQUARE(+x):Theresultis36.将被替换成:+x*+x。这种运算顺序C语言没有给出规定,而这时对不同的编译器可能出现不同的结果,gcc4.3.2是在乘法运算前进行了x自加操作。而编译器也可以产生5*6的情况。不一而别。这里就需要注意了,在宏中一般不要使用自增或自减运算符。2.#运算符:在宏中利用宏参数创建字符串。如果定义如下一个宏:#definePSQRXprintf(ThesquareofXis%dn,X*X这样使用宏:PSQR8);则输出为:ThesquareofXis64。该处双引号中的X并没有被替换,这是预处理的替换规则决定的。但是如果你希望在字符串中(双引号括起来的C语言认为是字符串)包含宏的参数。那么C语言提供了运算符来实现。例子程序如下:/*subst.c-substituteinstring*/#includestdio.h#definePSQR(x)printf(Thesquareof#xis%d.n,(x)*(x)intmain(void)inty=5;PSQR(y);PSQR(2+4);return0;输出如下:Thesq

      6、uareofyis25.Thesquareof2+4is36.可以看出第一次,用y代替了X。第二次用2+4代替了X。3.#运算符:预处理器的粘合剂:和运算符一样,运算符可以用于宏的替换部分。另外还可以用于类对象宏的的替换部分。这个运算符吧两个语言符号组合成单个语言符号。例子程序如下:/glue.c-usethe#operator#includestdio.h#defineXNAME(n)x#n#definePRINT_XN(n)printf(x#n=%dn,x#n);intmain(void)intXNAME(1)=14;/变成intx1=14;intXNAME(2)=20;/变成intx2=20;PRINT_XN(1);/变成printf(x1=%dn,x1);PRINT_XN(2);/变成printf(x2=%dn,x2);return0;输出如下:x1=14x2=20可以看到使用运算符后将x与n合并成一个字符串。可变参数宏:和_VA_ARGS_具体应用举例如下:#definePRprintf(_VA_ARGS_)假设之后用下面的方式调用该宏PRHowdy;PRwetigt=%d,

      7、shipping=¥%fn,wt,sp;则第一次调用中_VA_ARGS_展开为一个参数。Howdy第二次调用中_VA_ARGS_展开为3个参数。wetigt=%d,shipping=¥%fn,wt,sp展开后代码为:printfHowdy;printfwetigt=%d,shipping=¥%fn,wt,sp;需要注意一点,省略号只能代替最后的宏参数。如下定义是错误的。#defineWRONGX,.,Y#X#_VA_ARGS_#Y4.#include:文件包含。预处理器发现该指令后,就会寻找后跟的文件名并把该文件的内容复制包含到当前文件中。详细内容可参见C语言的变量作用域及头文件中关于头文件部分介绍。5.#undef取消定义:#undef指令取消已定义的一个给定#define。举例如下:例如;#defineLIMIT400#undefLIMIT/此处之后LIMIT是没有定义的。但是注意,C语言提供的几个预定义宏如:_DATE_和_FILE_等不可被取消。6.:#ifdef、#else和#endif及#ifndef:条件编译指令组合#ifdef、#else和#endif及#ifndef通

      8、过判断之后跟随的变量是否被#define定义而形成编译的条件。#ifdef判读后面的标识符是否为定义,而#ifndef则相反,判断是否未定义。#else则与两者中其一组合使用类似,if。else形式。#endif用于指示结束位置。7.#if与#elif:条件编译指令组合。#if指令更像C语言中if;#if后跟常量整数表达式,如果表达式为非零值,则表达式为真。#elif则可以与#if组合形成if。elseif。elseif的条件组合序列。(早期预处理器可能不支持#elif)。举例如下:#ifSYS=1#includetest1.h#elifSYS=2#includetest2.h#elifSYS=3#includetest3.h#else#includetest.h#endif8.#line和#error#line指令用于重置_LINE_和_FILE_宏报告的行号和文件名。使用举例:#line1000/把当前行重置为1000#line10cool.c/把行号重置为10,文件名重置为cool.c#error指令是预处理器发出一条错误消息,该消息饱和值了中的文本信息。可能的话编译过程应该中断。使用举例:#if_STDC_VERSION_!=199901L#errorNotC99#endif9.#pragma:编译器参数设定。这个指令在现代编译器中被扩展的比较强大,同时通过必要的指令集来完成编译指示。不做详细介绍。掌握以上预处理指令,和宏的实现。通过一些宏可以在编写程序时达到意想不到结果。二:宏的使用技巧举例:例一、用C宏,书写代码更简洁这段代码写网络程序的朋友都很眼熟,是Net/3中mbuf的实现。structmbufstructm_hdrmhdr;unionstructstructpkthdrMH_pkthdr;/*M_PKTHDRset*/unionstructm_extMH_ext;/*M_EXTset*/charMH_databufMHLEN;MH_dat;MH;charM_databufMLEN;/*!M_PKTHER,!M_EXT*/M_dat;上面的代码,假如我想访问最里层的MH_databuf,那么我必须写M_dat.MH.MH_dat.MH_databuf;这是不是很长,很难写呀?这样的代码阅读起来也不明了。其实,对于MH_pkthdr、MH_e

      《c 预处理 指令和c宏》由会员小**分享,可在线阅读,更多相关《c 预处理 指令和c宏》请在金锄头文库上搜索。

      点击阅读更多内容
    最新标签
    发车时刻表 长途客运 入党志愿书填写模板精品 庆祝建党101周年多体裁诗歌朗诵素材汇编10篇唯一微庆祝 智能家居系统本科论文 心得感悟 雁楠中学 20230513224122 2022 公安主题党日 部编版四年级第三单元综合性学习课件 机关事务中心2022年全面依法治区工作总结及来年工作安排 入党积极分子自我推荐 世界水日ppt 关于构建更高水平的全民健身公共服务体系的意见 空气单元分析 哈里德课件 2022年乡村振兴驻村工作计划 空气教材分析 五年级下册科学教材分析 退役军人事务局季度工作总结 集装箱房合同 2021年财务报表 2022年继续教育公需课 2022年公需课 2022年日历每月一张 名词性从句在写作中的应用 局域网技术与局域网组建 施工网格 薪资体系 运维实施方案 硫酸安全技术 柔韧训练 既有居住建筑节能改造技术规程 建筑工地疫情防控 大型工程技术风险 磷酸二氢钾 2022年小学三年级语文下册教学总结例文 少儿美术-小花 2022年环保倡议书模板六篇 2022年监理辞职报告精选 2022年畅想未来记叙文精品 企业信息化建设与管理课程实验指导书范本 草房子读后感-第1篇 小数乘整数教学PPT课件人教版五年级数学上册 2022年教师个人工作计划范本-工作计划 国学小名士经典诵读电视大赛观后感诵读经典传承美德 医疗质量管理制度 2 2022年小学体育教师学期工作总结 2022年家长会心得体会集合15篇
    关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
    手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
    ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.