C语言程序设计新视角-编译预处理_第1页
C语言程序设计新视角-编译预处理_第2页
C语言程序设计新视角-编译预处理_第3页
C语言程序设计新视角-编译预处理_第4页
C语言程序设计新视角-编译预处理_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

编译预处理NewPerspectiveforCProgranmming【主要内容】

•预处理的概念及特点;

•宏的定义及使用;

•文件包含的含义及使用;

•条件编译的规则及方法。【学习目标】

•领会文件包含的使用及效果,能够使用#include来开发较大的程序;

•能够使用#define创建普通的宏;

•理解条件编译。

19.1宏定义29.2文件包含39.3条件编译49.4本章小结目录CONTENTS

图9.1源程序生成执行文件的过程用C语言进行编程的时候,可以在源程序中包括一些编译命令,以告诉编译器对源程序如何进行编译。程序编译时,先处理这些编译命令,然后再进行源程序编译,所以,这些编译命令也被称为编译预处理。源程序生成执行文件的过程见图9.1。预处理命令字宏定义 #define、#undef

文件包含 #include

条件编译 #if、#ifdef、#else、#elif、#endif

预处理命令都是以“#”开头的。实际上,编译预处理命令不能算是C语言的一部分,但它扩展了C程序设计的能力,合理地使用编译预处理功能,可以使得编写的程序便于阅读、修改、移植和调试。

注意:预处理命令不是C语句,不能用分号结束19.1宏定义29.2文件包含39.3条件编译49.4本章小结目录CONTENTS9.1宏定义如果程序中有多个地方要用到同一个常量值,而且这些值在测试时有可能要根据需要改变,方便的做法应该是设一个专门的符号,只给这个符号在最初定义的地方赋值即可。在这个常量值需要改的时候只要改定义处的值就行了,不用从代码中一处一处地改,这样就不会因为漏掉某个地方而导致程序出错。这相当于做了一个文本替换的工作9.1.1简单的宏定义#define<宏名><字符串>define是宏定义命令的关键字;<宏名>是一个标识符;<字符串>可以是常数、表达式、格式串等。

说明:

(1)在程序被编译的时候,如果遇到宏名,先将宏名用指定的字符串替换,然后再进行编译。

(2)ANSI标准将替换过程称为宏替换。

(3)C语言程序普遍使用大写字母定义标识符。这种约定可使得读程序时很快发现哪里有宏替换。

(4)最好是将所有的#define放到文件的开始处或独立的文件中(用#include访问)。【例9-1】宏的例子1

用串替换标识符

#defineMAX128

voidmain()

{

intmax=MAX;

}编译器处理时,会直接把MAX替换成128。注意是文本替换,而不是变量赋值,程序中自始至终都不存在MAX这个量,相当于是用“查找→替换”功能查找MAX,并替换成128。

【例9-2】宏的例子2用串替换标识符。

#defineTRUE 1

#defineFALSE 0

printf("%d%d%d",FALSE,TRUE,TRUE+1);

输出:012【例9-3】宏的例子3宏代换的最一般用途是定义常量的名字。

#defineMAX_SIZE100

float balance[MAX_SIZE];

【例9-4】宏的例子4宏替换仅仅是以串代替标识符,而非字符串。

#defineE_MS"standarderroroninput\n"

printf(E_MS);

编译后printf语句实际是如下形式:

printf("standarderroroninput\n");

#defineXYZ thisisatest

printf("XYZ");/*此处"XYZ"为字符串*/

该段不打印"thisisatest"而打印"XYZ"。9.1.2带参数的宏定义

其中:

(1)<宏名>是一个标识符;

(2)(参数表)中的参数可以是一个,也可以是多个,当有多个参数的时候,每个参数之间用逗号分隔;

(3)<宏体>是被替换用的字符串,宏体中的字符串是由参数表中的各个参数组成的表达式。

#define<宏名>(参数表)<宏体>

#define命令的另一个特性是,宏名可以取参量。【例9-5】宏的例子5

#defineSUB(a,b)a-b

result=SUB(2,3);被替换为:result=2-3;

result=SUB(x+1,y+2);被替换为:result=x+1-y+2;

带参数的宏定义与函数类似,在宏替换时,就是用实参来替换<宏体>中的形参。【例9-6】宏的例子6

#defineMIN(a,b) (a<b)?a:bintmain()

{

int x,y;

x=10;

y=20;

printf("theminimumis:%d",MIN(x,y));

return0;

}

当编译该程序时,由MIN(a,b)定义的表达式被替换,x和y用作操作数,即printf语句被代换后取如下形式:

printf("theminimumis:%d",(x<y)?x:y);

用宏替换代替实在的函数的一大好处是宏替换增加了代码的执行速度,因为不存在函数调用的开销。但增加速度的代价是,由于重复编码而增加了程序长度。表9.1宏与函数的区别

虽然带参数的宏定义和带参数的函数很相似,但它们还是有本质上的区别,具体参见表9.1。

当一个函数中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。这样可以增加编程效率和程序的可读性。19.1宏定义29.2文件包含39.3条件编译49.4本章小结目录CONTENTS9.2文件包含

文件包含命令是把指定的文件插入该命令行位置,从而把指定的文件和当前的源程序文件连成一个源文件。文件包含命令格式#include<文件名>#include"文件名"或其中:

(1)include是关键字。

(2)文件名是指被包含的文件全名。如果文件名以尖括号括起,则在编译时将会在指定的目录下查找此头文件;文件名以双引号括起,则在编译时会首先在当前的源文件目录中查找该头文件,若找不到才会到系统的指定目录下去查找。

图9.2文件包含处理

预编译时,用被包含文件的内容取代该预处理命令,再把“包含”后的文件当做一个源文件进行编译,处理示意图见图9.2。文件包含的用处同系统多个文件,公用信息可单独组成一个包含文件当一个程序比较大时,可以把它分为多个功能相对独立的小程序,由多个程序员分别编程。这些小程序中有些公用的信息等可单独组成一个文件,在其他文件的开头用包含命令包含该文件即可使用。如符号常量、函数的定义等放到一个.h文件中(即文件扩展名为h的文件,称之为头文件)。在其他文件的开头用包含命令包含该头文件,这样,可避免在每个文件开头都书写那些公用量,从而节省时间,并减少出错。头文件可自己编写/系统提供例如stdio.h便是一个由系统提供的、有关输入/输出操作信息的头文件。【例9-7】编辑一个文件,在另外一个文件中被包含。voidfun(){printf("Hello!");}#include“stdio.h"#include"file1.c"intmain(){fun();return0;}保存为file1.c保存为file2.c包含文件file1.c注:file1.c和file2.c要在同一路径下,只要编译运行file2.c即可19.1宏定义29.2文件包含39.3条件编译49.4本章小结目录CONTENTS9.3条件编译条件编译命令可以使得编译器按不同的条件去编译程序不同的部分,产生不同的目标代码文件。通过条件编译命令,某些程序代码要在满足一定条件下才被编译,否则将不被编译。条件编译命令格式一商业软件公司广泛应用条件编译来提供和维护某一程序的各种用户版本。#ifdef标识符

程序段1

#else

程序段2

#endififdef、else和endif都是关键字。程序段1和程序段2是由若干预处理命令和语句组成的。它的功能是,如果标识符已被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译。本格式中的#else也可以没有【例9-8】条件编译命令的例子1

1 #include<stdio.h>

2 #defineTIME

3 intmain()

4 {

5

#ifdefTIME

6

printf("Nowbegintowork\n");

7

#else

8

printf("Youcanhavearest\n");

9 #endif

10 return0;

11 }

TIME是否已被#define语句定义过来决定编译哪一个printf语句。如果定义过,则编译第6行语句,否则编译第8行语句。本例TIME已经定义过输出的结果为:Nowbegintowork条件编译命令格式二#ifndef标识符

程序段1

#else

程序段2

#endif格式二与格式一形式上的区别在于ifdef关键字换成了ifndef关键字,其功能是:如果标识符未被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译。这与格式一的功能正好相反。条件编译命令格式二

#ifndefNULL

#defineNULL((void*)0)

#endif

本段代码能够保证符号NULL只有一次定义为((void*)0)。

条件编译命令格式三#if常量表达式程序段1#else

程序段2#endif

if、else和endif是关键字。程序段1和程序段2都是由若干条预处理命令和语句组成的。它的功能是:如常量表达式的值为真(true),则对程序段1进行编译;否则对程序段2进行编译。因此可以使程序在不同条件下完成不同的功能。【例9-9】条件编译命令的例子2

1 #include<stdio.h>

2 #defineR1

3 intmain()

4 {

5 floatc,s;

6 printf("inputanumber:");

7 scanf("%f",&c);

8 #ifR

9 s=3.14*c*c;

10 printf("areaofroundis:%f\n",s);

11 #else

12 s=c*c;

13 printf("areaofsquareis%f\n",s);

14 #endif

15 return0;

16 }

如果常量表达式R为真,则编译第9、10行语句,否则编译第12、13行语句

多种编译选择的情况

#if常量表达式1

程序段1

#elif常量表达式2

程序段2

#elif常量表达式3

程序段3

#else

程序段n+1

#endif【例9-10】条件编译的应用场合便于程序的移植#ifdefTURBO_C…

//TurboC独有的内容#endif#ifdefBORLAND_C…

//BorlandC独有的内容#endif#ifdefVISUAL_C…

//VisualC独有的内容#endif#defineDEBUG……#ifdefDEBUGprintf(……);//临时结果#endif若希望生成BorlandC版本,添加:

#defineBORLAND_C若希望生成VisualC版本,添加:

#define

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论