C语言中编译预处理命令的解读与应用

C语言中编译预处理命令的解读与应用


2024年4月26日发(作者:)

电脑编程技巧与维护 

C语言中编译预处理命令的解读与应用 

王秀芳,孙承爱,路燕 

(山东科技大学信息科学与工程学院,青岛2665 10) 

摘 要:编译预处理是由预处理程序模块负责完成,在编译前对源程序进行的预加工处理,是C语言的一个重要特 

点。对C语言中编译预处理的3条命令deifne、include、ifdef进行了详细分析,用实例对其特殊功能和用法做了详 

细的阐述,时C语言编译预处理命令的分析对c语言教学和学习都有帮助作用。 

关键词:编译预处理;#define;#include;#ifdef 

C Language Compilation Command Interpretation 

and Application of Pretreatment 

WANGXiufang.SUN Cheng'ai,LU Yah 

(College of Info.Science and Engg.SUST,Qingdao 266510) 

 ̄lract,Compiler preprocessor module by pretreatment for completion before the source for compiling the pre—processing is 

an important feature of the C language.This article on the C language compilation command of the three pretreatment define, 

include,ifdef analyzed in detail,with examples of its use of special features and a detailed exposition of this paper,C compiler 

preprocessor analysis of the C Language Teaching and learning are helpfu1. 

 ̄:lst compiled pretreatment;#define;样include;#ifdef 

1编译预处理 

语句的一般格式是: 

编译预处理是在编译前对源程序进行的预加]-处理,由 

#define符号常量名常量值 

预处理程序模块负责完成。其执行过程是:在对源程序进行 

符号常量名一般用大写字母表示。预处理程序对符号常量 

编译之前.预处理模块首先对源程序进行扫描,如果程序巾 

的替换不作语法检查,只是原样替换。带参数的宏定义一般 

有预处理命令,系统将自动引用预处理程序对源程序中的预 

形式为: 

处理部分进行分析和处理。处理之后再对源程序进行正式编 

#define宏名(参数表)表达式 

译.以形成目标代码。 

例如.在源程序中要使用到求a、b中两个值中较小值的函 

预处理语句通常以“#”开始,语句末尾不加分号,以区 

数,可在程序开头作下面的宏定义: 

别于C语句。它们可以出现在程序中的任何位置,其作用域 

#define MIN(a,b)((a)<(b))?(a):(b) 

是自}}J现点到所在源程序的末尾。但一般书写源程序时,往 

在程序中则可引用MIN(a,b)以表示取a、b中的较小值 

往将预处理语句置于开头部分。 

参加运算。 

编译预处理是C语言的一个重要特点。它能改善程序设 

2.1优点 

计的环境,有助于编写易移植、易调试的程序,也是模块化 

在使用宏定义时,宏名往往比宏体简单得多,因此,可 

程序设计的一个丁具。因此,对编译预处理命令的灵活运用, 

以省去许多重复的输人工作。比如下列程序对输入格式做宏 

可以使程序结构优良,更加易于调试和阅读。 

定义,就可以减少许多输入的麻烦。 

预处理语句主要有“文件包含”、 “宏替换”、 “条件编 

#include<stdio-h> 

译”3类。 

#define P print 

对包含文件。预处理程序要将被包含的文件之源代码嵌 

#defineD“%dkn” 

#define F“%f\l1” 

于被编译程序的相应位置,参加正式的编译以形成目标代码; 

main 0 

对宏定义.预处理程序要对相应符号进行宏替换;对条件编 

{ 

译.预处理程序要根据条件确定源程序中的哪些部分要参加 

int x=6,y=7,z=_8; 

正式编译形成目标代码.哪些部分不形成目标代码。 

2宏定义命令(#define) 

作者简介:王秀芳(1965一),女,硕士,副教授,研究方向: 

宏定义是用预处理命令#define指定的预处理。宏定义有 

数据库原理与应用、信息安全;孙承爱,硕士,副教授;路 

无参宏定义和有参宏定义两种。无参宏定义又叫符号常量宏 

燕.博士。副教授。 

定义。其实质是用标识符代替一串字符串。符号常量宏定义 

收稿日期:2010—08—23 

22一 

S0FrWARE DEVEL0PMENT AND DESIGN 

lfoat a=3.56,b=2.87,c=8.96; 

P(D,X,y);P(F,a,b);P(D F,Z,C); 

} 

由于宏定义可以一次定义,多次使用,并且宏名往往是见 

名知义,所以使用宏能增强程序的可读性。同时宏定义也可 

以进行嵌套,即先定义宏名,可以使用它再去定义新的宏名。 

2.2宏定义中括号的重要作用 

在宏定义中,字符串内的形参通常要用括号括起来,不 

仅如此,整个字符串也应该用括号括起来以避免出错。例如: 

#define f(x)x x+2x+l 

主程序中如果有语句m=9*f(x);程序原意是求9(x2+2x+ 

1)的值,由于宏定义只是简单的字符串的替换,上面的定义 

求出的就是9*x*x+2x+l的值,显然这个结果不是我们所要的。 

因此,宏定义中字符串也应该用括号括起来,正确的语句为 

#define f(x) (x*x+2x+1)。 

3文件包含命令#include 

预处理命令#include的作用是将被包含的文件的源代码嵌 

于被编译程序的相应位置,以参加正式编译形成目标代码。 

文件包含语句的格式为: 

#inelude<文件名> 

或#inelude”文件名” 

这两条语句的区别是:如果#include语句中用()括住文 

件名.则预处理程序按编译系统所在的文件缺省路径寻找文 

件名,这个缺省文件路径就是在进行C语言编译系统的安装 

时,按安装步骤提示形成的一个缺省路径。若用“”括住一 

个含有路径的文件名,则预处理程序首先搜索该路径所指目 

录.若未找到所指文件.则再到编译系统的缺省设定目录下 

搜索。因此.若想将自己所写的另一段源程序嵌入目前被编 

译程序中,应注意被嵌入源程序位于哪个目录下。一般情况 

下,最好将所有源程序放在同一目录中,在#include语句中用 

双引号“”指明路径.在编译时就不会发生找不到包含文件 

的错误 

3.1.h文件中的内容 

任何一个C程序都是由一个主函数main 0和一些自定义 

函数及对库函数的调用构成的。程序的执行从主函数开始, 

主函数结束。在程序中若有对某一函数的调用,只要被调函 

数源代码在主调函数的源代码后面,则需用#include语句嵌入 

相应的文件f如stdio.h)或者在主调函数中先进行函数声明。 

头文件.h中的代码是对相应函数的原型及符号常量等进行的 

说明和定义:而库函数的函数体代码则是以目标代码的形式 

存于库中的,在进行连接时方连人执行代码中。 

3.2文件包含可以包含的文件类型 

由于文件包含命令常放在文件的开头.所以常称这些文 

件为头文件。并以.h作为文件扩展名,其中h即为head的意 

思。由此可知包含文件可以包含其他任何扩展名的文本文件, 

例如.c的文件。以下就是一个包含.c扩展名的简单例子: 

include<file.c> 

main 0 

软件开发与设计 

{ 

int a'b; 

prinff Cinput a and b:”); 

prinff(“%d、n”,fe(a,b)); 

} 

文件file.e的内容是: 

fe(int x,int y) 

{ 

return(x>y?x:y); 

} 

文件包含不仅可以包含任何扩展名的文本文件,而且这 

些文件的包含还可以嵌套,即包含文件可以嵌套,只是需要 

注意嵌套文件的顺序。 

4条件编译语句 

条件编译就是编译系统按照不同的条件对不同的程序部 

分进行编译,因而产生不同的目标代码文件。也就是说,条 

件编译是在满足一定条件下才对某些程序段进行编译,不满 

足条件的程序段就不进行编译。这样做的好处是可编译出适 

应不同环境条件的目标代码文件,使得程序适应于不同情况, 

同时缩短代码的长度。提高程序的可读性和执行效率。条件 

编译有两类,一类是以是否定义某一符号常量作编译条件; 

另一类则以表达式的值是否为真作为编译条件。 

第一类条件编译语句格式为: 

#ifdef常量名 

程序段1 

#else 

程序段2 

#endif 

这类条件编译语句的功能是:若所指符号常量名已经定 

义,则对程序段l进行编译,否则对程序段2进行编译。 

第二类条件编译语句格式为: 

#if表达式 

程序段l 

#else 

程序段2 

#endif 

这类条件编译语句的功能是:若表达式为真.则编译程 

序段1,否则编译程序段2。 

4.1在函数主体中使用条件编译命令 

如果使用条件语句编写的函数中条件选择的程序段很长, 

般使用条件编译语句。因为条件语句将会对整个源程序进 

行编译.这样生成的目标代码程序很长.相应的执行效率就 

会降低。而采用条件编译,可以根据条件只编译其中的程序 

段1或者程序段2,生成的目标代码相对较短,因而执行效率 

就相对较高。比如下列程序使用了条件编译语句: 

#defineA=l 

main 0 

{ 

float c,r,s; 

pfinff(“input r:”); 

scanf(“,%f’,&r); 

23— 

电脑编程技巧与维护 

撕t A 

泽命令有效地解决这个问题。方法如下: 

c=2 3.14159 r: 

|}f1 C 

printf(“c=% ”,C); 

#include“f2

C” 

#else 

椭nclude“f3.C” 

s=3.14159 r r: 

//f2.C 

prinff(“s=%fln”,S); 

#ifndef MY 

#endif 

#deftne MY 

} 

#include“f3.C” 

该程序根据表达式是否成立.即A的值是否为真,分别 

#include<stdio-h> 

输 圆的周长和面积的值。另外,在对所编写的程序进行调 

#endif 

试时,也可以使用条件编译.使程序满足不同要求的if爿试条 

t|f3 C 

件,以方便调试。 

fndef MY 

#deftne MY 

4.2在头文件中使用条件编译命令 

椭nclude<stdio-h> 

在头文件中使用条件编译语句要注意的一点就是避免出 

托ndif 

现头文件的重复包含问题。如果一个工程中包含很多文件, 

5结语 

这样在文件的相互调用中就很容易形成文件的重复包含,从 

编译预处理是C语言的一个重要特点.若能清楚理解并 

而使得编译失败。比如一个工程中有3个文件:f1.c、f2.c、 

掌握这一技术,会使C程序的设计更加方便,减少不必要的 

f3.c'它们的头文件的包含情况如下: 

调试错误,节省调试时间,对C语言编泽系统的理解更加深 

||f1 C 

入,便于提高程序设计效碍曩,从而设计出高质量的C程序。 

舶nclude“f2.C” 

缃nclude“t"3.C” 

本课题得到IIJ东科技大学群星计划项目(qx0902081)资 

||f2 C 

助 

衔nclude“f3.C” 

参考文献 

撕nclude<stdio-h> 

【11杨峰.C语言完全手册.北京:科学出版社,2008. 

//f3.C 

[21谭浩强.C程序设计基础.北京:清华大学出版社,2007. 

#include<stdio_h> 

【3】孙成爱,赵卫东.程序设计基础一基于C语言.北京:清 

当对上面的程序进行编译时,就会出现重复包含文件< 

华大学出版社.2008. 

stdio.h>的问题,从而使得编译失败。此时,可以通过条件编 

f上接第7页1 

<list> 

配置的服务对象提供相应的服务。 

<value>logAdvice</value> 

4结语 

,/可以添加多个通知 

</list> 

以上是Spring AOP提供的几种比较简单且常用的通知类 

</prope ̄y> 

型和通知部署的几种简单方式,当然,Spring还提供了很多其 

</bean> 

他的方式,限于篇幅,这里不再进行说明。一般情况下,这几种 

在上面的配置中.指定了BeanNameAutoProxyCreator类的 

Spring通知(拦截器)的使用在中小型Web项目中还是有一定 

两个属性:beanNames和interceptorNames,beanNames指定了 

的适应性,对于初学者学习更深层次的AOP应用也有比较好的 

要进行自动代理的目标对象,interceptorNames与手动代理模 

借鉴作用。 

式巾的这个属性含义相同,指定了提供服务的对象。 

参考文献 

测试代码为: 

[1]柳永坡,刘雪梅,赵长海.JSP应用开发技术【MJ.北京: 

ApplicationCOntext context=flew ClassPathXmlApplica— 

人民邮电出版社,2005.9. 

tionContext(”applicationContext.xml”); 

【2】赵景晖.Java程序设计[M】.北京:机械工业出版社, 

BookBiz bookBiz: fB00kBiz1contex【.getBean(”bookBizTarget 

2008.1. 

”1://从配置文件中读取目标业务类,创建实例对象 

[3]北京阿博泰克北大青鸟信息技术有限公司.开发基于JSP/ 

bookBiz.buy(”吴文”,”Java程序设计”,48); 

Servlet/JavaBean的网上交易系统fM】.北京:科学技术 

这里不再是获取的代理对象,而是直接获得目标对象了。 

文献 版社.2008.1. 

由于存XML配置文件中指定了为目标对象进行自动代理,因 

[4]李刚.轻量级J,aV ̄t EE企业应用实战[M】.北京:电子工 

此当获取目标对象时.Spring会自动为其创建代理对象,并根据 

业出版社,2008 11. 

24一 


发布者:admin,转转请注明出处:http://www.yc00.com/web/1714143258a2389766.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信