C语言函数PPT课件.ppt
模块化程序设计函数孙小松1 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数26.1 函数的概念C程序结构C C程序结构如图所示程序结构如图所示1.1.一个一个C C程序可以分为若干个函数程序可以分为若干个函数2.2.每个程序有且只有一个主函数每个程序有且只有一个主函数(main),(main),其他都是子函数其他都是子函数3.3.子函数可以相互调用子函数可以相互调用, ,但主函数不能被但主函数不能被调用调用4.4.一个一个C C源程序由一个或多个文件构成源程序由一个或多个文件构成, ,每个文件就是一个编译单位每个文件就是一个编译单位 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数3说明说明: :1.1.一个一个C C程序的执行从主函数程序的执行从主函数(main)(main)开始开始, ,调用其他函数后仍回到调用其他函数后仍回到mainmain主函数结束主函数结束. .2.2.每个子函数都是平行的每个子函数都是平行的, ,任何子函数都任何子函数都不从属于其他函数不从属于其他函数3.3.从用户角度从用户角度, ,函数可以分为函数可以分为: : 标准函数标准函数, ,即库函数即库函数 用户自定义函数用户自定义函数4.4.从函数形式可以分为从函数形式可以分为: : 无参函数无参函数:printstar:printstar()() 有参函数有参函数:printf(“hello:printf(“hello”)”)#include void printStar() printf(“*n”);void printMessage() printf(“Hello, world.n”); printStar();void main() printStar(); printMessage(); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数4函数定义的一般形式函数定义的一般形式函数定义的一般形式: : 类型说明类型说明 函数名函数名(形式参数说明形式参数说明) 函数体函数体 形式参数说明方法形式参数说明方法: : 数据类型数据类型 变量名变量名,类型类型 变量名变量名 无参数函数定义形式无参数函数定义形式: : 类型说明类型说明 函数名函数名()() 函数体函数体 void printHellovoid printHello()() printf(“hello!n printf(“hello!n”);”); 有参数函数定义形式有参数函数定义形式: : 类型说明类型说明 函数名函数名( (形式参数说明形式参数说明) ) 函数体函数体 int sum(int x, intint sum(int x, int y) y) int int z; z; z=x+y z=x+y; ; return(z return(z);); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数5函数体函数体一般情况下一般情况下, ,函数体有两部分组成函数体有两部分组成: : 局部变量说明局部变量说明 语句语句; ; 局部变量说明局部变量说明: : 函数体内的变量函数体内的变量. .其有效范围仅在本函数其有效范围仅在本函数体内起作用体内起作用, ,离开本函数无意义离开本函数无意义. .int sum(int x, intint sum(int x, int y) y) int int z; z; /局部变量定义局部变量定义 z=x+yz=x+y; ; return(z return(z);); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数6函数的参数和函数的值一个程序由若干个函数组成一个程序由若干个函数组成, ,各函数各函数调用时经常要传递一些数据调用时经常要传递一些数据, ,即即调用函调用函数数把数据传递给把数据传递给被调用函数被调用函数, ,经过经过被调被调用函数用函数处理后处理后, ,得到一个确定的结果得到一个确定的结果, ,在在返回返回调用函数调用函数时时, ,将结果带回将结果带回调用函数调用函数. .#include stdio.h#include int max(int x, intint max(int x, int y) y) int int z; z; z=(xy) ? x : y; z=(xy) ? x : y; return(z return(z);); void main()void main() int a,b,c int a,b,c; ; scanf(“%d%d”,&a scanf(“%d%d”,&a, &b);, &b); c = max(a c = max(a, b);, b); printf(“max is %dn”,c printf(“max is %dn”,c);); 主函数主函数子函数子函数 . . c = max(a,bc = max(a,b);); . .int max (intx, intint max (intx, int y) y) . . . . . .return (z); return (z); a,bz各函数之间数据往来通过各函数之间数据往来通过参数传递参数传递和和返回语句返回语句实现实现 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数7函数参数函数参数: :用于函数间数据的传递用于函数间数据的传递形式参数形式参数: :定义函数定义函数时给出的参数时给出的参数实际参数实际参数: :调用函数调用函数时给出的参数时给出的参数#include stdio.h#include int max(int max(intint x, intx, int y y) ) int int z; z; z=(xy) ? x : y; z=(xy) ? x : y; return(z return(z);); void main()void main() int a,b,c int a,b,c; ; scanf(“%d%d”,&a scanf(“%d%d”,&a, &b);, &b); c=max( c=max( a a , , b b ); ); printf(“max is %dn”,c printf(“max is %dn”,c);); 对于函数对于函数max有两个形式参数有两个形式参数x,y形式参数形式参数x和和y只在只在max函数中使用函数中使用a,b是主函数中定义的变量是主函数中定义的变量, 当当main函数调用函数调用max函数时函数时. a,b成为成为max的实际参数的实际参数调用时调用时, 实际参数的值赋给形参进行处理实际参数的值赋给形参进行处理例例:max接受到两个值接受到两个值:23 89max返回返回89一、形式参数和实际参数一、形式参数和实际参数 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数8#include stdio.h#include int max(int max(intint x, intx, int y y) ) int int z; z; z=(xy) ? x : y; z=(xy) ? x : y; return(z return(z);); void main()void main() int a,b,c int a,b,c; ; scanf(“%d%d”,&a scanf(“%d%d”,&a, &b);, &b); c=max( c=max( a a , , b b ); ); printf(“max is %dn”,c printf(“max is %dn”,c);); 说明说明:1.定义函数时定义函数时,必须说明形参的类型必须说明形参的类型,形参只能形参只能 是是变量变量(包括数组包括数组). 不能是常量或表达式不能是常量或表达式2.函数被调用之前函数被调用之前,形参和子函数中的变量形参和子函数中的变量不占内存不占内存,调用结束返回调用结束返回,形参所占的内存被收回形参所占的内存被收回.3.实参可以是实参可以是常量、变量或表达式常量、变量或表达式. 因为传递过来的是具体数值因为传递过来的是具体数值.4.实参和形参类型必须一致实参和形参类型必须一致(或可以安全转换或可以安全转换).5.C语言中语言中,实参和形参传递的是实参和形参传递的是”按值传递按值传递”,即单向传递即单向传递, 只与参数相对位置有关只与参数相对位置有关,而与而与变量名无关变量名无关int b, int aintint c; c;c=( ab ) ? a :b;c=( ab ) ? a :b;return(creturn(c););1320main-amain-bmax-amax-b1320 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数9#include int sum(int a, int b) a=a+b; b=a+b; return(a);void main() int a=1,b=3,c; c=sum(a,b); printf(“sum of %d,%d is %dn”,a,b,c);阅读下面程序,写出运行结果阅读下面程序,写出运行结果函数被调用之前函数被调用之前,形参和子函数中的变量形参和子函数中的变量不占内存不占内存,调用结束返回调用结束返回,形参所占的内存被收回形参所占的内存被收回.实参和形参传递的是实参和形参传递的是”值传递值传递”,即单向传递即单向传递, 只与参数相对位置有关只与参数相对位置有关,而与而与变量名无关变量名无关sum of 1,3 is 4sum of 1,3 is 4 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数10二、函数返回值二、函数返回值#include stdio.h#include int max(int max(intint x, intx, int y y) ) int int z; z; z=(xy) ? x : y; z=(xy) ? x : y; return(z return(z);); void main()void main() int a,b,c int a,b,c; ; scanf(“%d%d”,&a scanf(“%d%d”,&a, &b);, &b); c=max( c=max( a a , , b b ); ); printf(“max is %dn”,c printf(“max is %dn”,c);); 函数值也就是函数的返回值函数值也就是函数的返回值,是一个是一个具体确定的值具体确定的值.函数使用函数使用returnreturn语句返回值。语句返回值。一个函数内可以有多个一个函数内可以有多个returnreturn语句,语句,执行到任何执行到任何returnreturn语句,函数都将立即语句,函数都将立即返回到调用函数返回到调用函数if(xif(xy)y) return(x return(x););elseelse return(y return(y););returnreturn后面的后面的()()可以省略可以省略, ,可以返回可以返回一个表达式一个表达式, ,先求解表达式的值先求解表达式的值, ,再返回再返回. .int max(int x, intint max(int x, int y) y) return xy?x:y return xy?x:y; ; 1.1.返回函数值的方法返回函数值的方法 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数11#include stdio.h#include int max(int max(intint x, intx, int y y) ) int int z; z; z=(xy) ? x : y; z=(xy) ? x : y; return(z return(z);); void main()void main() int a,b,c int a,b,c; ; scanf(“%d%d”,&a scanf(“%d%d”,&a, &b);, &b); c=max( c=max( a a , , b b ); ); printf(“max is %dn”,c printf(“max is %dn”,c);); 2.函数值的类型函数值的类型 函数的类型即函数值的类型函数的类型即函数值的类型. .例如例如, ,函数函数 maxmax是是intint型型, ,函数的返回值也是函数的返回值也是intint型型. .省略了类型说明的函数就是省略了类型说明的函数就是intint型型. .returnreturn中表达式的值一般和函数中表达式的值一般和函数类型相同类型相同. .如果不一致如果不一致, ,则需要进行类型转换则需要进行类型转换. .以以 函数类型为准函数类型为准. . C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数123.不需要返回的函数不需要返回的函数如果函数中没有如果函数中没有return, return, 认为是认为是 一个过程一个过程, ,可以使用类型可以使用类型void.void.如果一个函数被声明如果一个函数被声明voidvoid类型类型, ,就不允许就不允许 再引用它的返回值。只能单纯调用它。再引用它的返回值。只能单纯调用它。#include void printStar() printf(“*n”);void printMessage() printf(“Hello, world.n”); printStar();void main() printStar(); printMessage(); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数13函数的调用一、函数调用一般形式一、函数调用一般形式一般形式一般形式: 函数名函数名(实参列表实参列表)说明说明: :如果调用无参函数如果调用无参函数, ,实参表列可以忽略实参表列可以忽略, , 但括号不能省但括号不能省. .实参个数和形参个数相同实参个数和形参个数相同. .实参和形参类型一一对应实参和形参类型一一对应, ,必要时会进必要时会进行类型转换行类型转换. .注意注意: :不同系统中不同系统中, ,实参的计算顺序不同实参的计算顺序不同. . 一般认为从右到左一般认为从右到左计算和计算和赋值赋值. . 一般在调用函数前计算出实参的值一般在调用函数前计算出实参的值例1 读程序,写出结果#include int f(int a, int b) int c; if(a b) c = 1; else if(a = b) c = 0; else c = -1; return c;void main() int i = 2, p; p = f(i, +i); printf(“%d”, p); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数14二、函数调用方式二、函数调用方式1、函数语句、函数语句 形式为形式为: :函数函数( (实参表列实参表列););例如例如: :printMessageprintMessage();();printf(“%d”,pprintf(“%d”,p););说明说明: :这种方式不要求函数带返回值这种方式不要求函数带返回值, ,函数只执行一定操作函数只执行一定操作. .2 2、函数表达式函数表达式 函数的返回值参与运算函数的返回值参与运算例如例如: :m = max(a,bm = max(a,b););m = 3 m = 3 * * max(a,b max(a,b););printf(“%d”,max(a,bprintf(“%d”,max(a,b););说明说明: :这种方式的函数不能用于这种方式的函数不能用于voidvoid类型类型 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数15三、函数调用的执行过程三、函数调用的执行过程从右到左的顺序从右到左的顺序, ,计算实参中各计算实参中各表达式值表达式值. .按照位置按照位置, ,将实参的值一一将实参的值一一传递给形参传递给形参. .执行被调用函数执行被调用函数. .当遇到当遇到return(return(表达式表达式) )语句时语句时, ,计算表达式的值并返回主调函数计算表达式的值并返回主调函数. .例2 读程序,写出结果#include int iabs(float x) return (x 0 ? x : -x);void main() float x = -0.6, y; y = iabs(2 * x); printf(“x=%f,iabs(x)=%fn”, x, y);1234X= -0.600000,iabs(x)=1.000000 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数16四、函数的原形四、函数的原形在程序中调用函数需满足以下条件在程序中调用函数需满足以下条件: :被调用函数必须存在被调用函数必须存在, ,且必须遵循且必须遵循“先定义后使用先定义后使用”的原则的原则如果被调用函数的定义在主调函如果被调用函数的定义在主调函数之后数之后, ,可以在调用之前给出可以在调用之前给出原形原形说明说明. .原形说明原形说明: :类型说明类型说明 函数名函数名( (参数类型参数类型, ,参数类型参数类型) ) C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数17函数的嵌套调用嵌套调用是指在一个函数的函数体嵌套调用是指在一个函数的函数体中又调用了其他函数中又调用了其他函数. .程序执行过程程序执行过程: :第一层第一层 第二层第二层 第三层第三层 main() printStar() printStar(); printfMessage() printMessage(); printStar(); printStar(); 结束#include void printStar() printf(“*n”);void printMessage() printf(“Hello, world.n”); printStar();void main() printStar(); printMessage(); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数18例例3 3 编程求编程求)!( !mnmnCmn分析分析: : 重复三次不同的阶乘运算重复三次不同的阶乘运算, ,只是每次的值不同只是每次的值不同. .将求阶乘的过程编程一个函数将求阶乘的过程编程一个函数facfac, ,以不同的参数值来调用以不同的参数值来调用facfacfackk!#include #include float fac(int k); float t=1.0; int i; for(i=2;i1n1时时11nnxxx当当n=0n=0时时当当n!=1n!=1时时 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数20 函数的递归调用是指在调用一个函数时又直接或间接函数的递归调用是指在调用一个函数时又直接或间接调用函数本身调用函数本身. . 直接调用直接调用 间接调用间接调用 递归调用必须引入一个递归调用必须引入一个循环条件控制递归结束循环条件控制递归结束, ,否则进入死循环否则进入死循环. . C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数21例例4 4 有有5 5个人坐在一起个人坐在一起, ,问第问第5 5个人多少岁个人多少岁? ?答答: :比第比第4 4个人大个人大2 2岁岁; ;第第4 4个人说他比第三个人大个人说他比第三个人大2 2岁岁; ;第第3 3个人比第个人比第2 2个人大个人大2 2岁岁, ,第第2 2个人比第个人比第1 1个人大个人大2 2岁岁. .而第而第1 1个人有个人有1010岁岁. .问第问第5 5个人多少岁个人多少岁? ? 计算公式计算公式: :2)1(10)(nagenage(n=1)(n1)回推阶段递推阶段 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数22 函数调用过程函数调用过程#include int age ( int n) int c; if (n=1) c=10; else c=age(n-1) + 2; return c;void main() printf(“ %d “, age(5); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数23例例5 5 用递归调用求用递归调用求n!n!阶乘阶乘(n=0)(n=0)使用循环做使用循环做: :float facfloat fac( int( int n) n) float f=1; float f=1; if (n=0) if (n=0) for(i for(i=2; i=n; i+)=2; i=n; i+) f f * *= i;= i; else f else f=-=-1;1; return f; return f; #include float fac (int n) float f; if (n1) f=fac(n-1) * n; else if (n=0|n=1) f=1; else f=-1; return f;void main() int n; float y; printf(“input a integer number:”); scanf(“%d”, &n); y = fac (n); if (y1) C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数24根据变量的作用域作用域不同,可分为局部变量局部变量和全局变量全局变量两种。1变量的作用域变量的作用域变量的作用域:变量的作用域:变量起作用的范围。局部变量:局部变量:在函数内部或某个控制块的内部定义的变量。局部变量的作用域:函数内部。作用:增强了函数模块的独立性。全局变量:全局变量:在函数外面定义的变量称为全局变量。全局变量的作用域:从该变量定义的位置开始,直到源文件结束。作用:在同一文件中,所有函数都可以引用全局变量。增强了各函数间数据的联系。 6.2 变量的作用域 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数25局部变量和全局变量的作用域如图所示: int i; main() float a, b; char s; function(); int k; void fuction(); int m; 局部变量 s 的作用域 局部变量 a, b 的作用域 全局变量 i 的作用域 全局变量 k 的作用域 局部变量 的作用域 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数26阅读程序【例6-4】的程序, 了解变量作用域。请注意区分局部变量局部变量和全局变量全局变量的作用域。程序:程序: example6_4.c C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数27变量的存储类别一、变量的动态存储和静态存储一、变量的动态存储和静态存储全局变量和局部变量全局变量和局部变量 变量的作用域变量的作用域静态存储和动态存储静态存储和动态存储 变量的存储类别变量的存储类别: :生存期生存期内存中供用户使用的空间有内存中供用户使用的空间有: : 代码区代码区 静态存储区静态存储区: :编译时分配空间编译时分配空间 动态存储区动态存储区: :执行时分配空间执行时分配空间变量或函数的属性变量或函数的属性: :数据类型存储类型自动型auto静态型static寄存器register外部型extern C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数28二、局部变量的存储类别二、局部变量的存储类别1 1、自动类别、自动类别 存储在动态存储区存储在动态存储区, ,用用autoauto说明说明如如: : int func1( int int func1( int a) a) autoauto int int b, c=3; b, c=3; 形参形参a, a, 变量变量b,cb,c都是自动变量都是自动变量, ,调用函数时调用函数时, ,系统给它们分配存系统给它们分配存储空间储空间, ,函数调用结束时函数调用结束时, ,自动自动释放空间释放空间. .通常通常autoauto可以省略可以省略 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数292 2、局部静态变量、局部静态变量 占用静态存储占用静态存储, ,用用staticstatic说明说明说明说明: :局部静态变量局部静态变量, ,属于静态存储类别属于静态存储类别, , 在程序执行的整个过程中在程序执行的整个过程中, ,都不释放都不释放 存储空间存储空间. .局部静态变量在编译时赋值局部静态变量在编译时赋值, , 仅赋值一次仅赋值一次. .如果定义局部静态变量没有赋初值如果定义局部静态变量没有赋初值, , 系统会自动赋初值系统会自动赋初值. .局部静态变量局部静态变量, ,只有在定义它的函数只有在定义它的函数 内被引用内被引用( (它存在它存在, ,但不被其他函数引用但不被其他函数引用) )如果如果f f不定义成不定义成staticstatic是什么结果是什么结果? ?f=1;j=1; fac(1): f=f*n=1*1=1; 输出1!=1;j=2; fac(2): f=f*n=1*2=2; 输出2!=2;j=3; fac(3): f=f*n=2*3=6; 输出3!=6;j=4; fac(4): f=f*n=6*4=24; 输出4!=24; C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数303 3、寄存器变量、寄存器变量 存储在寄存器中存储在寄存器中, ,用用registerregister说明说明说明说明: :计算机的寄存器个数有限计算机的寄存器个数有限. .寄存器变量对寄存器占有是动态的寄存器变量对寄存器占有是动态的有的系统对寄存器变量转化为有的系统对寄存器变量转化为 自动变量处理自动变量处理, ,而有的系统会而有的系统会 自动设置寄存器变量自动设置寄存器变量. . C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数31三、全局变量的存储类别三、全局变量的存储类别1.1. 全局变量都存放在静态的存储区。全局变量都存放在静态的存储区。2.2. 用用staticstatic关键字声明的全局变量,只能在本文件内使用。关键字声明的全局变量,只能在本文件内使用。3.3. 没有用没有用staticstatic关键字的全局变量可以在别的文件中使用关键字的全局变量可以在别的文件中使用externextern关键字声明为关键字声明为外部变量外部变量,并在该文件中作为全局变,并在该文件中作为全局变量使用。量使用。尽量少使用全局变量尽量少使用全局变量/* a.c */int max;void calcMax(int a, int n) ./* main.c */extern int max;void main() . printf(“%d”,max); ./* a.c */static int max;void calcMax(int a, int n) ./* main.c */extern int max;void main() . printf(“%d”,max); .错!max未定义错!不能引用max C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数32四、存储类别小结四、存储类别小结1 1、变量的定义方法、变量的定义方法 存储类别存储类别 数据类型数据类型 变量名变量名2 2、变量的划分、变量的划分按作用域划分按作用域划分: :按生存期按生存期局部变量局部变量全局变量全局变量自动变量自动变量静态变量静态变量寄存器变量寄存器变量形式参数变量形式参数变量动态存储动态存储静态存储静态存储自动变量自动变量形式参数形式参数寄存器变量寄存器变量静态局部变量静态局部变量全局变量全局变量按变量的存放位置按变量的存放位置动态存储区动态存储区静态存储区静态存储区自动变量自动变量形式参数形式参数静态局部变量静态局部变量全局变量全局变量寄存器寄存器寄存器变量寄存器变量 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数33自定义的函数有两种:内部函数内部函数和外部函数外部函数。1内部函数内部函数 若函数的存储类型为static型,则称其为内部函数内部函数(内部函数又称为静态函数),它表示在由多个源文件组成的同一个程序中,该函数只能在其所在的文件中使用,在其他文件中不可使用。内部函数的声明形式: static ();例如:例如: static int Statistic ();2外部函数外部函数 若函数的存储类型定义为extern型,则称其为外部函数外部函数,它表示该函数能被其他源文件调用。函数的默认存储类型为extern型。 6.3 内部函数与外部函数 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数34 外部函数的应用示例。下面的程序由3个文件组成:file1.c、file2.c、example6_6.c。 在file1.c、file2.c中分别定义了两个外部函数; 在example6_6.c中可以分别调用这两个函数。1file1.c/* file1.c 外部函数定义 */extern int add(int m, int n) return (m+n);2file2.c/* file2.c 外部函数定义 */extern int mod(int a, int b) return(a%b); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数353example6_6.c#include extern int mod(int a, int b);/*外部函数声明*/extern int add(int m, int n);/*外部函数声明*/main() int x, y, result1,result2,result; printf(Please enter x and y:n); scanf (%d%d, &x, &y); result1=add(x,y);/*调用file1中的外部函数*/ printf(x+y=%dn,result1); if (result10) result2=mod(x,y);/*调用file2中的外部函数*/ result=result1-result2; printf(mod(x,y)=%dn,result2); printf(x+y)-mod(x,y)=%dn, result); C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数36关于程序的几点说明关于程序的几点说明(1)在程序file1.c、file2.c中的函数定义可以不需要extern加以说明,默认为外部函数。(2)在example6_6.c中对外部函数的声明也可以不用extern加以说明,默认为外部函数。(3)由多个源文件组成一个程序时,main()函数只能出现在一个源文件中。(4)由多个源文件组成一个程序时,有3种连接方式: 将各源文件分别编译成目标文件,得到多个目标文件(.obj后缀),然后用连接命令把多个.obj文件连接起来。 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数37建立项目文件(.prj后缀或.dsw后缀),具体操作可参阅各种C语言集成开发环境说明。使用文件包含命令。请参阅本章6.6节。(5)如果将file1.c或file2.c中的extern改成static,则主程序在编译时无法通过。(6)在程序file1.c或file2.c中,也可以互相调用其外部函数。Turbo c的连接接命令为的连接接命令为tlink 例如:例如:tlink example6_6.obj+file1.obj+file2.obj 结果结果:生成一个example6_6.exe文件。 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数38 6.4 编译预处理 作用:作用: 在在对源程序编译之前做一些处理对源程序编译之前做一些处理, ,生成扩展生成扩展C C源程序源程序 种类种类 宏定义宏定义 #define 文件包含文件包含 #include 条件编译条件编译 #if-#else-#endif等等 格式:格式:“#”#”开头开头占单独书写行占单独书写行语句尾不加分号语句尾不加分号 C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数39如 #define YES 1 #define NO 0 if(x=YES) printf(“correct!n”); else if (x=NO) printf(“error!n”);展开后: if(x=1) printf(“correct!n”); else if (x=0) printf(“error!n”); 1 宏定义宏定义不带参数宏定义不带参数宏定义 一般形式一般形式 #define #define 宏名宏名( (标识符标识符) ) 宏体宏体 (字符串)(字符串) 功能功能: :用指定标识符用指定标识符( (宏名宏名) )代替字符序列代替字符序列( (宏体宏体) ) 宏展开:预编译时宏展开:预编译时, ,用宏体来替换宏名用宏体来替换宏名-不作语法检查不作语法检查如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);说明说明: :1.1.定义位置定义位置: :任意任意( (一般在函数外面一般在函数外面) )2.2.作用域作用域: :从定义命令到文件结束从定义命令到文件结束3.3.# #undefundef可终止宏名作用域可终止宏名作用域 格式:格式: #undef#undef 宏名宏名例 #define YES 1 main() . #undef YES #define YES 0 max() . YES原作用域YES新作用域5.5.宏定义可嵌套,不能递归宏定义可嵌套,不能递归例 #define MAX MAX+10 ()4.4.引号中的内容与宏名相同也不置换引号中的内容与宏名相同也不置换例 #define PI 3.14159 printf(“2*PI=%fn”,PI*2);宏展开:printf(“2*PI=%fn”,3.14159*2);6.6.宏定义中使用必要的括号宏定义中使用必要的括号()例 #define WIDTH 80 #define LENGTH WIDTH+40 var=LENGTH*2;宏展开:var= 80+40 *2;( )( )例 #define WIDTH 80 #define LENGTH WIDTH+40 var=LENGTH*2;宏展开: var=WIDTH+40*2 var=80+40*27 7. .只是简单替代,标识符不占内存空间只是简单替代,标识符不占内存空间8 8. .一般宏名使用大写字母形式一般宏名使用大写字母形式. . C语言程序设计 第第 6 章章 模块化程序设计函数模块化程序设计函数40带参数宏定义带参数宏定义 一般形式:一般形式: #define #define 宏名宏名( (参数表参数表) ) 宏体宏体例 #define S (r) PI*r*r相当于定义了不带参宏S,代表字符串“(r) PI*r*r” 说明:说明: 1.1.宏展开:不仅宏体替换宏展开:不仅宏体替换, ,还要进行还要进行形参形参替换替换 2.2.宏体及各形参外一般应加括号宏体及各形参外一般应加括号()() 3.3.宏名与宏名与参数之间不能有空格参数之间不能有空格例 #define S(a,b) a*b . area=S(3,2);宏展开: area=3*2;不能加空格例 #define POWER(x) x*x x=4; y=6; z=POWER(x+y