C程序设计南京工业大学ppt课件.ppt

上传人:牧羊曲112 文档编号:2075944 上传时间:2023-01-07 格式:PPT 页数:85 大小:263.50KB
返回 下载 相关 举报
C程序设计南京工业大学ppt课件.ppt_第1页
第1页 / 共85页
C程序设计南京工业大学ppt课件.ppt_第2页
第2页 / 共85页
C程序设计南京工业大学ppt课件.ppt_第3页
第3页 / 共85页
C程序设计南京工业大学ppt课件.ppt_第4页
第4页 / 共85页
C程序设计南京工业大学ppt课件.ppt_第5页
第5页 / 共85页
点击查看更多>>
资源描述

《C程序设计南京工业大学ppt课件.ppt》由会员分享,可在线阅读,更多相关《C程序设计南京工业大学ppt课件.ppt(85页珍藏版)》请在三一办公上搜索。

1、C+Programming,函数和编译预处理 第5章,引言函数的定义和调用函数的原型说明与值调用函数的嵌套和递归调用作用域和存储类内联函数具有缺省参数值的函数函数重载编译预处理程序的多文件组织,C+Programming,引言,随着模拟对象的复杂性增加,程序将会变得越来越复杂和冗长。在编写一个较大的程序时,为了便于管理,可以采用一些较好的编程策略,常用的方法是按功能或操作将程序分割成一些具有特定功能的、相对独立的且便于管理和阅读的小模块。本章主要介绍这种分割工具之一:函数,包括函数的定义、函数的调用、参数的传递方法、内联函数、函数的重载、变量的作用域等,另外简要介绍编译预处理以及程序多文件组织

2、的编译和连接方法。,C+Programming,函数的定义和调用,函数概述 函数定义 函数调用,5.1,C+Programming,函数概述,C+中的函数就是具有特定功能的模块。函数是构成C+程序的基本单位,C+程序的运行都是由主函数(main()开始,然后通过一系列函数调用来实现各种功能。从用户角度看,函数包括用户自定义函数和系统库函数。从函数的形式来看,函数可以分为无参函数、有参函数、无返回值函数和有返回值函数等。除了main()函数以外,一个函数既可以被其它函数调用,也可以调用其它函数。图5-l反映了函数的层次组织结构以及相互之间的调用关系。,5.1.1,C+Programming,系统

3、库函数,库函数也称为标准函数,是在C+编译系统中已经预先定义的函数。C+把一些常用的操作以库函数的方式提供给用户,包括常用的数学计算函数(如:sqrt()、fabs()等)、图形处理函数、标准输入/输出函数等。按功能对库函数进行分类,将同类库函数集中在一个头文件中,用户只要在程序中包含相应的头文件,就可以使用该头文件中的所有库函数。,C+Programming,用户自定义函数,在程序设计过程中,用户可根据自己的需要将一段完成功能相对独立的代码定义为一个函数,这类函数称为用户自定义函数。本章将主要介绍用户自定义函数的定义和调用方法。,C+Programming,图5-1 函数调用和被调用的层次关

4、系,C+Programming,函数定义,对于库函数,在头文件中已经定义好了,调用函数前只需包含相应的头文件即可;对于用户自定义的函数,要先完成函数的定义,然后才可以调用它。根据函数定义和使用时参数的不同,可将函数分为两类:无参函数和有参函数。无参函数 有参函数 函数返回值和return语句,5.1.2,C+Programming,无参函数,定义无参函数的一般格式为:(void)/函数体 为函数返回值的类型,它可以是任一标准数据类型或导出数据类型,当没有返回值时,类型必须为void。函数名为用户给函数起的名字,其命名规则与标识符相同。后的括号”()”称为函数调用运算符,对于无参函数,函数调用运

5、算符内可以为空,也可以为void。函数返回值为整型时,可省略类型标识符int。当函数无返回值时,必须规定其类型为void。示例,C+Programming,示例,void Message(void)cout”*n”;cout”very good!n”;cout”*n”;该函数完成输出一些问候语。像这类与外部环境之间没有任何数据交换的函数,通常将其定义为无参函数。,C+Programming,有参函数,定义有参函数的一般格式为:类型()/函数体 有参函数中类型与的含义和要求与无参函数一致。为该函数的参数的类型和名字,中的参数称为形式参数或形参,形参的个数是没有限制的,当超过一个参数时,参数间一定

6、要用逗号”,”分隔开,且每个参数都要有类型说明。示例 在定义有参函数时,必须标明每个参数的类型,即使参数的数据类型相同,也不能将参数合在一起用一个类型说明符。,C+Programming,示例,例如,求两个整数中的大数,函数可定义为:int Max(int x,int y)/A return(xy?x:y);该函数有两个整型参数x,y,函数的返回值是整型。如上例A行写成以下形式就是错误的:Max(int x,y),C+Programming,函数返回值和return语句,函数的返回值也称为函数值。当函数有返回值时,在函数体中必须使用return语句来返回该函数的值。return语句的一般格式为

7、:return;或 return();这里可以为任意合法的表达式。当执行该语句时,首先求出表达式的值,再将该值转换成函数定义时规定的返回值的类型后,将其作为函数的返回值。【例5.1】求三角形的面积,C+Programming,函数调用,C+中,函数的功能是通过在程序中对其调用来实现的。调用一个函数,就是把控制权转去执行该函数的函数体,函数体执行完之后,再将控制权转到调用函数处。无参函数的调用格式 有参函数的调用格式 函数调用的使用方式 关于形参和实参的几点说明【例5.2】输入三个实数,求出其中的最大数图5-2,5.1.3,C+Programming,无参函数的调用格式,无参函数的调用格式一般为

8、:函数名()在调用无参函数前,必须先定义与它同名的无参函数。如:Message函数定义过之后,可以使用Message();来调用。,C+Programming,有参函数的调用格式,有参函数的调用格式一般为:函数名()中的参数称为实际参数或实参,每个实参可以是任一合法的表达式。实参与形参不同,在实参前没有数据类型说明符。在调用有参函数前,也必须先定义,另外,调用有参函数时实参表和形参表的参数类型、个数必须匹配。如:Max(4,9);及 Max(a*4,b);函数的调用过程是:先计算各实参表达式的值(对有参函数),然后将所求的值传递给相应的形参,执行函数体,执行完毕再返回到函数的调用处,继续执行其

9、后继语句。,C+Programming,函数调用的使用方式,对于有返回值的函数,可以用两种方式调用:一种方式是函数调用出现在表达式中,其值(也称为函数值)参与表达式的运算;另一种方式是用一个语句来实现调用,即在调用格式后加上一个分号,构成函数调用语句,在这种情况下,函数返回值不起任何的作用。对于没有返回值的函数,函数调用只能通过函数调用语句实现。,C+Programming,关于形参和实参的几点说明,定义函数时指定的形参,在未出现函数调用时,它们不占用内存中的存储单元。只有在函数调用时,形参才被分配内存单元,在调用结束后,形参所占的内存单元也被释放。调用时是将实参的值传递给形参,只是一个单向的

10、传递关系。这是我们所说的“值传递”,形参值的改变不会影响实参的值。实参与形参的类型应相同。当类型不一致时,则它们应该兼容,即按照不同类型数值的赋值规则,将实参转换为形参的数据类型后再传递给形参。,C+Programming,图5-2 函数的调用过程,C+Programming,函数的原型说明与值调用,函数的原型说明 函数的值调用,5.2,C+Programming,函数的原型说明,C+中,与变量一样,函数的定义和使用也必须遵循先定义后使用的原则。如果函数的调用在函数的定义之前,就会出现编译错误。如果函数调用在前、定义在后,则在函数调用之前,必须要对被调用的函数作原型说明。函数原型说明是一条语句

11、,它必须以分号结束。函数原型说明的一般格式函数原型说明的目的是告诉编译程序,该函数的参数个数、各参数的类型和返回值类型。函数原型说明可以出现在程序中的任何位置,只要在调用前即可,且对函数原型说明的次数没有限制。,5.2.1,C+Programming,函数原型说明的一般格式,类型();或 类型();函数原型说明的形参和返回值的类型必须与对应的函数定义一致,对于第一种格式,原型说明中形参表的形参名可以和定义时的形参名不一致,又由于形参在原型说明中并不起任何作用,因此可以省略形参名(即第二种格式)。,C+Programming,函数的值调用,C+中,形参与实参的结合方式有三种:传值调用、传地址调用

12、和引用调用。传值调用简称为值调用。值调用的特点是:在被调用函数的执行过程中,只能改变形参,不能改变实参。【例5.3】值传递应用两数交换 图5-3值传递的好处是使得函数具有完全的独立性,函数的执行对其外界的变量没有影响。在值传递的情况下,函数只能通过return语句返回一个值或不返回任何值。要用函数实现两个数参数的交换,值传递是无法实现的,可以用地址传递或引用传递的方法。,5.2.2,C+Programming,图5-3两数交换函数调用过程示意图,C+Programming,函数的嵌套和递归调用,函数的嵌套调用 函数的递归调用,5.3,C+Programming,函数的嵌套调用,C+语言的函数之

13、间是相互平行、独立的,在定义一个函数时,不允许在其函数体内再定义另一个函数,即函数不允许嵌套定义。但是函数之间的嵌套调用是可以的,即在定义一个函数时,在函数体内又调用另一个函数。图5-4【例5.4】求一元二次方程ax2+bx+c=0的根,5.3.1,C+Programming,图5-4 嵌套调用,main函数,b函数,a函数,调用a函数,结束,调用b函数,C+Programming,函数的递归调用,在函数A的定义中调用函数A,或在函数A的定义中调用函数B,而在函数B的定义中又调用了函数A,这类函数的自调用关系称为递归调用。前一种情况称为直接递归,而后一种情况称为间接递归。在C+语言中,这两种递

14、归调用都是允许的。【例5.5】用函数递归调用方法求5!【例5.6】将参数逐位正序和反序输出【例5.7】Hanoi(汉诺塔)问题,5.3.2,C+Programming,【例5.5】用函数递归调用方法求4!,分析:由递推公式n!=n*(n-1)!,所以求n!的问题可以转化为求(n-1)!的问题,(n-1)!=(n-1)*(n-2)!,因此求(n-1)!的问题可以转化为求(n-2)!的问题,依此类推,直到转化为求1!的问题,根据定义,1!=1,则从1!=1开始将上述过程逆向求解,就可以求出n!。这种求解问题的方法可用函数递归调用方法实现算法演示程序代码,C+Programming,算法演示,C+P

15、rogramming,程序代码,#include int f(int n)if(n=0|n=1)return 1;/A else return n*f(n-1);/B void main(void)coutf(4)n;,C+Programming,【例5.6】将参数逐位正序和反序输出,设计两个函数,其参数都为整型,分别将参数逐位正序和反序输出。要求用递归函数实现。分析:要实现逐位正序或反序输出一个整数,则须获取它的各位数字。如1234,则用1234%10获得它的个位数,求十位数,则须先将个位数去掉,即1234/10,结果为123,再求个位数即可,依此类推。求一个整数K的各位数字时其递推关系为:

16、f1=K tn=fn%10 fn+1=fn/10 其中tn为整数K的第n位数字(从右数起),fn为去掉K的右边n-1位数后剩下的数。而该递推关系的结束条件为fn=0。程序代码,C+Programming,【例5.7】Hanoi(汉诺塔)问题,这是一个经典的数学问题:有三个塔A、B、C,开始时A塔上有n个盘子,盘子大小不等,大的在下,小的在上,如图5-6所示。要求将这n个盘子从A塔移到C塔,但每次只允许移一个盘子,而且在移动过程中始终保持大盘子在下,小盘子在上,在移动过程中可以利用B塔。分析移动步骤递归公式程序代码,C+Programming,图5-6汉诺塔问题,C+Programming,C+

17、Programming,分析,可以用递归的思想来考虑这个问题。假设能将A塔中最上面的n-1个盘子借助于C塔移动到B塔,然后将A塔中剩下的一个盘子移动到C塔,再将B塔中的n-1个盘子借助于A塔移动到C塔,这样问题就解决了。因此接下来就要考虑如果一个塔内有n-1个盘子,如何借助于另一个塔移动到C塔,与n个盘子的思考方法一样,此时可考虑先移动n-2个盘子,依次类推,当变成移动一个盘子时,递归结束。,C+Programming,移动步骤,将n个盘子从A塔移到C塔上,可以分解为以下3个步骤:将A塔上的n-1个盘子借助C塔先移到B塔上;将A塔上剩下的1个盘子移到C塔上;将n-1个盘子从B塔借助于A塔移到C

18、塔上。其中第一步和第三步又可以分解为类似的三步,依次类推,直到A中只剩下一个盘子时,递归结束。,C+Programming,递归公式,将k-1个盘子从一个塔借助于另一个塔移动到第三个塔上(k1),它是一个递归的过程。用函数Hanoi(int k,char A,char B,char C)表示,其中第一个参数k为要移动盘子的个数,第二个参数A为初始塔,第三个参数B为中间塔,第四参数C为目标塔。该函数的功能是将A塔中的k个盘子通过B塔移动到C塔。将1个盘子从一个塔移到另一塔上。用Move(char A,char B)实现,即将A塔中的盘子移动到B塔中去。,C+Programming,作用域和存储类

19、,作用域是指程序中所说明的标识符的适用范围。C+中的作用域共分为:块作用域、文件作用域、函数原型作用域、函数作用域和类作用域。存储类型决定了变量的生存期,即何时为变量分配存储空间以及何时撤消存储空间。在定义变量时,通常根据该变量的不同用途,为其指定相应的存储类型。作用域 存储类型,5.4,C+Programming,作用域,作用域描述的是标识符起作用的范围,这里的标识符可以泛指变量、常量或函数原型说明等。但对编译预处理中宏定义中的宏名却不适用。块作用域 函数原型作用域 函数作用域 文件作用域,5.4.1,C+Programming,块作用域,用花括号括起来的程序段构成一个块(即复合语句),在块

20、内说明的标识符只能在该块内使用,其作用域就称为块作用域。具有块作用域的标识符的有效范围是从声明处开始,到块结束处为止,该作用域的范围是具有局部性的。因此,在块内定义的变量称为局部变量。示例对于块作用域,C+语言做如下的规定:块嵌套问题 对一些特殊情况,C+作不同的处理,C+Programming,块嵌套问题,块嵌套问题。当块A包含块B,则在块B中可以使用在块A中定义的标识符,反过来则不行。另外当在块A中定义的标识符与块B中定义的标识符同名时,则在块B中的标识符将屏蔽块A中的同名标识符,即局部优先【例5.8】块嵌套中标识符的使用,C+Programming,对一些特殊情况,C+作不同的处理,对i

21、f语句或switch语句的表达式中定义的标识符,其作用域在该语句内。例如在for语句的第一个表达式中声明的标识符,其作用域为包含该for循环语句的那个块。例如 定义有参函数时,形式参数的作用域为块作用域,即它的适用范围为整个函数体,C+Programming,例如,void Block4()if(int i=2)/i的作用域从此行开始 i+=1;else i+=2;/i的作用域到此行结束coutiendl;/错误,i没有定义,C+Programming,例如,void Black5()for(int i,j=0;i10;i+)/A int j=9;/与A行定义的j没有冲突,couti+jt;i

22、nt i=10;/错误,与A行定义的i同名cout”i=”in;,C+Programming,函数原型作用域,函数原型声明(没有函数体)中参数的作用域称为函数原型作用域。此时,参数的作用域开始于函数原型声明的左括号,结束于函数原型声明的右括号。比如:void Fun(int x,int y);x=2;/错误,x没有定义 由于函数原型声明中的参数名与函数定义以及函数调用均无关,因此,函数原型声明中参数的标识符可以与函数定义中参数的标识符不同,甚至在函数原型声明时可以只列出参数的类型,而没有参数名。比如:void Fun(int,int);,C+Programming,函数作用域,函数作用域是指在

23、函数体内定义的标识符在其定义的函数内均有效。该标识符在函数的任何位置都可以使用它,不受先定义后使用的限制,也不受函数体中嵌套块的限制。C+中,只有标号具有函数作用域,即在一个函数体内定义的标号,在该函数的任何位置都可以调用该标号(条件语句、循环语句、switch语句中的特殊情形除外)。且正是由于标号为函数作用域,因此在一个函数中不能用goto语句调用另一个函数中的标号。例如,C+Programming,例如,void Fun(int x)int y;lab1:couty;lab1:y+=x;/错误,与A行的标号同名,尽管它们属于不同的块 if(!y)goto lab1;else goto la

24、b2;/错误,不能调用其它函数中的标号 void Fun1(int x)lab2:coutxn;,C+Programming,文件作用域,具有文件作用域的标识符是在所有函数定义之外定义的,即该标识符不隶属于任何块。它的作用域从标识符声明处开始,一直到文件结束。具有文件作用域的变量称为全局变量。当在块作用域内的变量与全局变量同名时,局部变量优先。此时若想在该块中调用全局变量,可通过作用域运算符“:”来实现。【例5.9】在块作用域内引用文件作用域同名变量,C+Programming,存储类型,作用域是从空间上对标识符进行划分的,而存储类型则是从变量存在的时间(即生存期)来划分变量。变量的存储类型可

25、以分为静态存储方式和动态存储方式两大类。在C+中,变量的存储类型分为四种:自动(auto)类型、寄存器(register)类型、静态(static)类型和外部(extern)类型。自动类型变量 静态类型变量 寄存器类型变量 外部类型变量,5.4.2,C+Programming,静态存储方式,在程序开始执行时就为变量分配存储空间,直到程序执行结束时,才收回为变量分配的存储空间,这种变量称为静态存储变量,其生命期为整个程序执行过程。,C+Programming,动态存储方式,在程序的执行过程中,为其分配存储空间的变量称为动态存储变量。对于动态存储变量,当程序运行到该变量的定义处时为其分配存储空间,

26、而当程序运行到该变量所在作用域的结束处时自动收回为其分配的存储空间。因此动态存储类型的变量的生存期为其所在的作用域。,C+Programming,自动类型变量,用关键字auto修饰的变量称为自动类型的变量。在说明局部变量时,编译系统默认其为自动类型变量,因此通常省略关键字auto。自动类型的变量只能是局部类型的变量,不可能为全局变量。示例自动类型变量属于动态存储类型变量。上例中的x,y的生存期为其所在的作用域。具体说,对x而言,在A行为其分配4个字节的存储空间,到B行就收回该存储空间。在使用自动类型的变量之前必须对其赋初值。否则,其值为一个不确定的随机数。,C+Programming,auto

27、 int I;/错误,全局变量不能用关键字/auto修饰void Au(void)auto int x=1;/A x为自动类型变量 char y=a;/省略关键字auto 系统默/认y为自动类型变量/B,C+Programming,静态类型变量,静态存储类型的变量有两种:全局变量和静态类型变量。用关键字static修饰的变量称为静态类型变量。静态类型变量可以为局部变量,也可以为全局变量。静态类型变量属于静态存储变量,即在程序开始运行时就为其分配存储空间,当程序结束时才释放其所占用的存储空间。因此在整个程序执行过程中,静态变量都始终占用同一个存储空间。【例5.10】使用静态类型的局部变量,C+P

28、rogramming,寄存器类型变量,用关键字register修饰的局部变量称为寄存器类型变量,这类变量也采用动态存储的分配方式。在编译过程中,编译器不为寄存器类型的变量分配内存空间,而是直接使用CPU中的寄存器,以便提高对这类变量的存取速度。寄存器类型变量主要用于控制循环次数等不需要长期保存值的变量。【例5.11】利用寄存器类型变量求l15的阶乘。,C+Programming,#include void main(void)register float Fact=1;/定义实型寄存器变量Fact for(register int i=1;i=15;i+)/定义整型寄存器变量i Fact*=i

29、;couti!=Factn;,C+Programming,外部类型变量,用关键字extern修饰的变量称为外部类型变量,外部类型变量必须是全局变量。在C+中,有两种情况下需要使用外部类型变量。在同一个源程序文件中,当在全局变量的定义之前使用该变量时,在使用前要对该变量进行外部类型变量声明。【例5.12】外部类型变量的声明 当程序由多个文件组成时,若在一个源程序文件中要引用在另一个源程序中定义的全局变量,在引用前必须对所引用的变量进行外部声明。【例5.13】文件间共享全局变量,C+Programming,【例5.12】外部类型变量的声明,#includeint Max(int x,int y)r

30、eturn xy?x:y;void main(void)extern int a,b;/AcoutMax(a,b);/Bint a=12,b=-4;,C+Programming,【例5.13】文件间共享全局变量,extern float x;/Avoid main(void)x+;coutxn;在文件c2.cpp中有:float x=100;/B,C+Programming,内联函数,一般函数在调用时,要花费将实参和返回地址压入栈,然后转入执行被调用函数等一系列开销。C+中的内联函数,将省略这类的开销。编译系统对内联函数的处理与一般函数的处理方式不同,在编译调用内联函数的语句时,编译器将内联函

31、数的代码插入到函数调用处,在运行过程中,将直接运行插入的代码,从而可以提高程序运行的速度。将一个函数声明为内联函数时,只要在函数定义前加关键字inline即可,声明格式【例5.14】用内联函数计算立方体的体积,5.5,C+Programming,内联函数声明格式,inline(参数表)/函数体,C+Programming,【例5.14】用内联函数计算立方体的体积,#include inline float Cube(float a)return a*a*a;void main()coutside;cout”边长为”side”的立方体的体积为:”Cube(side)n;/A,C+Programm

32、ing,具有缺省参数值的函数,在定义具有缺省参数值的函数时,要为参数指定一个值。比如:void Fun(int x=1,int y=2)【例5.15】具有缺省参数值的延时函数【例5.16】求圆柱体的体积,5.6,C+Programming,【例5.15】具有缺省参数值的延时函数,#includevoid Delay(int n=1000)/Afor(;n0;n-);void main(void)cout延时500个单位时间n;Delay(500);/Bcout延时1000个单位时间n;Delay();/C,C+Programming,【例5.16】求圆柱体的体积,#include#define

33、 PI 3.1415926float Volume(float r,float h=10);/Avoid main(void)float r,h;coutrh;coutr;cout第二个圆柱体的体积为:Volume(r)n;float Volume(float=5,float=20);/Bcout第三个圆柱体的体积为:Volume()n;/Cfloat Volume(float r,float h)/Dreturn(PI*r*r*h);,C+Programming,函数重载,函数的重载又称函数名重载,是指实现不同功能的函数可以具有相同的函数名。C+编译器在进行函数调用时是根据函数名和函数的参数

34、来决定调用哪一个函数的,因此,对于函数名重载问题,要区分函数名相同的函数,只有从它们的参数上进行区分。要实现函数名重载,它们的参数必须满足下面两个条件之一:参数的个数不同 参数的类型不同【例5.17】利用参数类型的不同实现重载函数【例5.18】利用参数个数不相同实现重载函数在定义重载函数时要注意的几点,5.7,C+Programming,【例5.17】利用参数类型的不同实现重载函数,#include int Abs(int x)/A cout=0?x:-x;double Abs(double x)/B cout=0?x:-x;void main()cout”-20的绝对值是:”Abs(-20)

35、endl;/Ccout”-111.11的绝对值是:”Abs(-111.11)endl;/D,C+Programming,【例5.18】利用参数个数不相同实现重载函数,#include int max(int a,int b);int max(int a,int b,int c);int max(int a,int b,int c,int d);void main()coutmax(3,5)endl;coutmax(-7,9,0)endl;cout max(23,15,3,6)endl;,int max(int a,int b)return ab?a:b;int max(int a,int b,

36、int c)int t=max(a,b);return max(t,c);int max(int a,int b,int c,int d)int t1=max(a,b);int t2=max(c,d);return max(t1,t2);,C+Programming,在定义重载函数时要注意的几点,定义的重载函数必须具有不同的参数个数或不同的参数类型,只有这样编译系统才能根据不同的参数决定调用哪一个函数版本 仅仅是函数返回值不同并不能区分两个函数,因此不能根据函数的返回值定义函数的重载。例如 int sum(int a)void sun(int a)这两个函数仅仅返回值不同,编译时将发生二义性错

37、误。,C+Programming,编译预处理,C+语言中使用一些特殊的命令,在编译之前先对这些命令进行“预处理”,然后将结果和源程序一起进行编译处理,得到目标代码,此过程称为编译预处理。这些命令称为编译预处理指令,它们不是C+语句,一律以#开头,以回车符结束,每一条预处理指令独占一行。根据编译预处理功能的不同,将其分为三类:宏定义#define、文件包含#include和条件编译#if。“文件包含”处理 宏定义 条件编译,5.8,C+Programming,所谓“文件包含”处理是指一个源文件可以将另一个源文件的全部内容包含进来。“文件包含”可通过#include编译预处理指令来实现,格式为:#

38、include 或#include“文件名”“文件包含”的处理过程【例5.19】文件包含的应用 关于#include编译预处理指令需要说明的几点,“文件包含”处理,5.8.1,C+Programming,这种格式是标准格式,主要用于包含C+系统所提供的头文件。当C+预处理器遇到该指令时,就到C+系统目录的include子目录下搜索给出的文件,并把它嵌入到当前文件中。,C+Programming,这种格式既适合于用户自己建立的文件,也适合于C+系统提供的头文件。当C+预处理器遇到该指令后,首先在当前工作目录中查找所包含的文件,如果找不到,再按标准方式进行搜索。,C+Programming,“文件

39、包含”的处理过程,C+Programming,【例5.19】文件包含的应用,设文件File1.h的内容为:int x=200,y=100;float x1=25.6,x2=28.9;,设文件File2.cpp的内容为:#include“File1.h”/A#include void main(void)coutxtyn;coutx1tx2n;,int x=200,y=100;float x1=25.6,x2=28.9;#include void main(void)coutxtyn;coutx1tx2n;,C+Programming,关于#include编译预处理指令需要说明的几点,被包含的文

40、件通常是头文件,也可以为其他类型的文件,如源程序文件或文本文件等;一个#include命令只能指定一个被包含文件;一个被包含的文件中也可以包含其他文件,即文件的包含可以是嵌套的,嵌套的层次也没有限制;#include指令可以出现在程序中的任何位置,通常是放在程序的开头 由于被包含的文件(File1.h)与其所在的文件(File2.cpp)在预编译后已称为合并到一个文件中,因此,File2.cpp可直接访问File1.h中的全局变量,此时可不用extern声明。同样,File2.cpp中也能直接访问File1.h中的函数,C+Programming,宏定义,宏定义用#define编译预处理指令实

41、现,可分为不带参数的宏定义和带参数的宏定义。不带参数的宏常用于定义标识符常量,即可将一个常量指定给一个标识符,它与const类型的变量类似;带参数的宏可将一个表达式指定给一个带参数的标识符,它与函数的功能类似。不带参数的宏定义【例5.20】不带参数的宏的使用 带参数的宏定义【例3.23】带参数的宏定义的使用,5.8.2,C+Programming,不带参数的宏定义,定义不带参数宏的一般格式为:#define 标识符 字符序列 其中标识符称为宏名,它可以是任意合法的标识符,通常为大写。字符序列为一串字符,它可由任意的字符构成,包括空格。例如:#define PI 3.1415926 不带参数的宏

42、定义及其使用需说明的几点,C+Programming,不带参数的宏定义及其使用需说明的几点,宏名可以为任意的合法标识符,常用大写字母表示 宏定义中可以用已定义过的宏名,但对用双引号括起来的字符序列中的字符,即使与宏名相同,也不进行宏扩展。例如 宏扩展时,只对宏名作简单的代换,不作任何计算,也不作任何语法检查;比如宏定义不是C+语句,不必在行末加分号,如果加了分号则会连分号一起进行宏扩展,例如:一个宏通常在一行内定义完,并以换行符结束。当多于一行时,须使用转义字符“”进行连接。例如宏定义是一条预处理指令,它与变量定义的含义不同,即只作宏替换,不为宏分配内存空间,C+Programming,【例5

43、.20】不带参数的宏的使用,#include#define R 3#define PI 3.1415926#define L 2*PI*R/A 可以使用已定义的宏名#define S PI*R*R/B#define STR1 周长为:#define STR2 面积为:void main(void)coutSTR1LnSTR2Sn;/C,C+Programming,带参数的宏定义,带参数的宏在进行宏扩展之前,先要进行参数替换。定义带参数宏的一般格式为:#define()其中为宏的参数,只要给出参数名,不需要参数的类型,当有多个参数时,用逗号分隔开,与不带参数的宏的要求类似,不过这里的字符序列中要使用宏中的参数。,C+Programming,【例3.23】带参数的宏定义的使用,C+Programming,条件编译,5.8.3,C+Programming,程序的多文件组织,5.9,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号