电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本
换一换
首页 金锄头文库 > 资源分类 > DOC文档下载
分享到微信 分享到微博 分享到QQ空间

c 预处理 指令和c宏

  • 资源ID:89123292       资源大小:25KB        全文页数:9页
  • 资源格式: DOC        下载积分:12金贝
快捷下载 游客一键下载
账号登录下载
微信登录下载
三方登录下载: 微信开放平台登录   支付宝登录   QQ登录  
二维码
微信扫一扫登录
下载资源需要12金贝
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
如填写123,账号就是123,密码也是123。
支付方式: 支付宝    微信支付   
验证码:   换一换

 
账号:
密码:
验证码:   换一换
  忘记密码?
    
1、金锄头文库是“C2C”交易模式,即卖家上传的文档直接由买家下载,本站只是中间服务平台,本站所有文档下载所得的收益全部归上传人(卖家)所有,作为网络服务商,若您的权利被侵害请及时联系右侧客服;
2、如你看到网页展示的文档有jinchutou.com水印,是因预览和防盗链等技术需要对部份页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有jinchutou.com水印标识,下载后原文更清晰;
3、所有的PPT和DOC文档都被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;下载前须认真查看,确认无误后再购买;
4、文档大部份都是可以预览的,金锄头文库作为内容存储提供商,无法对各卖家所售文档的真实性、完整性、准确性以及专业性等问题提供审核和保证,请慎重购买;
5、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据;
6、如果您还有什么不清楚的或需要我们协助,可以点击右侧栏的客服。
下载须知 | 常见问题汇总

c 预处理 指令和c宏

C 预处理指令和C宏C预处理指令和C宏C语言程序在被编译成可执行文件时,也许你使用的IDE只需点击一下编译按钮,或者使用gcc编译器的,也是一条命令就完成了(当然使用命令时,会有些必须的参数)。但是真正实际情况,这个过程需要经历:预处理-编译-链接-装载。当然我们的编译器已经高度发达,将这些内容全部实现了。而预处理最长被我们使用一条指令是#include。我们用它来加载头文件。同时还会有些使用预处理指令的C宏或是编译条件等。一:首先先将C语言所有预处理指令简单介绍一下:1.#define指令:该条指令最常被用来定义符号常量或明显的常量,当然定一个"类函数"宏也是需要使用它的。每个#define行由三部分组成,第一部分是指令自身#define,第二部分是所选择的缩略语,这些缩略语称为宏(macro)。第三部分为宏替换的主体(或列表)。举例如下:#definePXprintf("xis%dn",x)#definePXprintf("xis%dn",x)预处理指令宏主体(替换列表)其中对于第二部分(宏)有如下要求:宏的名字中不能有空格,而且必须遵循C变量命名规则:只能使用字母、数字和下划线(_)而且第一个字符不能为数字。同时要注意,对于所有预处理指令都是从开始到第一个换行符结束。#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预处理指令宏(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("Afterincrementing,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之后的情况类似。特别指出: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"#x"is%d.n",(x)*(x)intmain(void)inty=5;PSQR(y);PSQR(2+4);return0;输出如下:Thesquareofyis25.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_)假设之后用下面的方式调用该宏PR"Howdy"PR"wetigt=%d,shipping=¥%fn",wt,sp;则第一次调用中_VA_ARGS_展开为一个参数。"Howdy"第二次调用中_VA_ARGS_展开为3个参数。"wetigt=%d,shipping=¥%fn",wt,sp展开后代码为:printf"Howdy"printf"wetigt=%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通过判断之后跟随的变量是否被#define定义而形成编译的条件。#ifdef判读后面的标识符是否为定义,而#ifndef则相反,判断是否未定义。#else则与两者中其一组合使用类似,if。else形式。#endif用于指示结束位置。7.#if与#elif:条件编译指令组合。#if指令更像C语言中if;#if后跟常量整数表达式,如果表达式为非零值,则表达式为真。#elif则可以与#if组合形成if。elseif。elseif的条件组合序列。(早期预处理器可能不支持#elif)。举例如下:#ifSYS=1#include"test1.h"#elifSYS=2#include"test2.h"#elifSYS=3#include"test3.h"#else#include"test.h"#endif8.#line和#error#line指令用于重置_LINE_和_FILE_宏报告的行号和文件名。使用举例:#line1000/把当前行重置为1000#line10"cool.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宏)为本站会员(小**)主动上传,金锄头文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即阅读金锄头文库的“版权提示”【网址:https://www.jinchutou.com/h-59.html】,按提示上传提交保证函及证明材料,经审查核实后我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.