- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第八章 预处理指令 本章要点 宏替换指令 文件包含指令 本章学习目标 理解预处理的含义 掌握简单宏替换和带参数宏替换的规则 掌握宏替换指令和文件包含指令的使用方法 预处理指令 以字符“#”开头,后面跟不同的指令名,如#include、#define 预处理指令不能直接进行编译。在编译之前必须对这些指令提前进行处理,即“预处理”。 C语言中常用的预处理指令包括以下三类:宏替换、文件包含、条件编译。 8.1 宏替换 8.1.1 简单宏替换 【例】编程实现求圆的周长、面积与球的体积。 在上述程序中,存在着如下问题: (1)常量3.1415926在程序中出现了三次,由于其包含字符较多,给程序的编写带来一定的麻烦; (2)如果在程序编写中将某位置的3.1415926输入错误,则对应的部分结果将出现错误,从而造成结果的不一致。 使用宏替换可以解决上面的问题,将程序8-1修改如下: 宏替换即用一个指定的标识符来代表一个替换序列,其一般形式为: #define 标识符 替换序列 其中标识符被称为宏名,替换序列其实是一个字符序列(可以包含标识符、关键字、常数、字符串常量、运算符、标点符号等)。 宏替换指令在程序编译前被预处理器处理,此时,预处理器将程序代码作为字符序列来对待,不考虑代码的含义。 预处理器遇到一个宏替换指令时,会登记“标识符”代表“替换序列”的信息,然后将后面的程序代码中出现的所有PI替换为3.1415926。替换完成后得到的程序代码和程序8-1相同。 真正被编译执行的是替换后的代码。 8.1.2 带参数的宏替换 其一般形式为: #define 标识符(形式参数列表) 替换序列 其中形式参数列表中可以包含若干个参数(参数之间用逗号分隔),每个参数均为一个标识符。这些参数可以在替换序列中出现多次。 在程序代码中,调用带参数宏替换的方式为: 宏名(实际参数列表) 其中每个实际参数均是一个字符序列(可以包含标识符、关键字、常数、字符串常量、运算符、标点符号等),实际参数的个数应和形式参数的个数相同。 预处理器遇到带参数的宏替换时,将登记相关的信息以便以后使用。在后面的程序代码中如果出现了宏调用,宏调用将被替换序列所取代,同时用每个实际参数替换对应的形式参数。 程序8-3替换后得到如下程序 使用宏替换指令需要注意: (1)宏替换不是语句,因此指令的最后通常不加分号,错误的添加分号(分号将被作为替换序列的一部分)可能会导致替换后得到的程序代码出现语法错误。如: #define PI 3.1425926; s = PI * r * r; 语句经预处理后会替换为: s = 3.1415926; * r * r 编译时会提示语法错误! (2)不论是带参数的宏还是不带参数的宏,在处理时预处理器只是进行字符序列的替换,不会执行其中的运算。例: #include stdio.h #define square(n) n*n main() { int a = 2; printf(“%d”, square(a+1)); } 进行替换后,square(a+1)会替换为a+1*a+1,而非(a+1)*(a+1)。这是由替换的规则所决定的。对于上述例子,我们可以做如下改进: #define square(n) (n)*(n) (3)定义带参数的宏时,宏名和左括号之间不能有空格,否则被认为是无参数的宏,“(形式参数列表)”将被作为替换序列的一部分。 #define square (n) n*n void main( ) { int a = 2; printf(“%d”, square(a+1)); } 预处理后上述程序代码会替换为: void main( ) { int a = 2; printf(“%d”, (n) n*n(a+1)); } 编译时编译器会提示错误。 (4)类似于全局变量,宏替换的作用范围是从它的定义开始直到源文件结束,但我们可以通过#undef预处理指令提前终止相应宏的作用范围。如 #define PI 3.1415926 void main( ) { … } #undef PI void func() { … } 则在func函数内不能使用PI宏定义,因为func函数不在PI的作用范围内。 (5)对于程序中用双引号括起来的字符串内的字符序列,即使同宏名相同也不被替换,例如: #define PI 3.1415926 void main( ) { …. printf(“PI=%f\n”, PI); } printf格式字符串内的PI不会被替换,而后面的PI将会被替换。 (6)带参数的宏替换从形式上来看与函数类似,但其实现方式与函数有本质的不同,二者的区别主要体现在以下几个方面: a.
文档评论(0)