大学C语言程序设计第二版(电子工业)第6章_第1页
大学C语言程序设计第二版(电子工业)第6章_第2页
大学C语言程序设计第二版(电子工业)第6章_第3页
大学C语言程序设计第二版(电子工业)第6章_第4页
大学C语言程序设计第二版(电子工业)第6章_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

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

文档简介

第6章函数与编译预处置6.1函数概述6.2函数的定义和阐明6.3函数的调用6.4函数的参数6.6变量的存储类型6.7内部函数和外部函数6.8编译预处置命令6.5函数的嵌套调用与递归调用

6.1函数概述

★函数是封装了一定功能的模块

★C言语是函数驱动式言语〔一个源程序文件由一个或多个函数组成〕#include“stdio.h〞voidmain()//函数头{inta=8;printf(“a=%d〞,a);}//函数体★一个C源程序必需有且只能有一个主函数main(

)。C程序总是从main(

)函数开场执行,最后终了于main(

)函数,其他函数是经过main(

)直接或间接调用完成其功能的。#include<stdio.h>intadd(intx,inty){ints;s=x+y;returns;}main(){inta=1,b=2,c;c=add(a,b);printf("%d\n",c);}kj61一、函数定义二、函数声明三、函数调用#include<stdio.h>main(){inta=1,b=2,c;intadd(intx,inty);c=add(a,b);printf("%d\n",c);}intadd(intx,inty){ints;s=x+y;returns;}函数概述〔1〕一个C程序由一个或多个源〔程序〕文件组成——可分别编写、编译和调试。〔2〕一个源文件由一个或多个函数组成,可为多个C程序公用。〔3〕C言语是以源文件为单位而不以函数为单位进展编译的。〔4〕在C言语中,一切函数〔包括主函数main(

)〕都是平行的。一个函数的定义,可以放在程序中的恣意位置,主函数main(

)之前或之后。但在一个函数的函数体内,只能调用其他函数,不能再定义另一个函数,即不能嵌套定义。〔5〕主函数名main是系统定义的,是运转时首先被调用的函数,它可以调用其他函数,但不能被其他函数调用;其他函数间可以相互调用,也允许嵌套调用。〔6〕从函数定义的角度看,函数可分为库函数和用户定义函数两种。①库函数:由C系统提供,用户无须定义,也不用在程序中进展类型阐明,只需在程序前写出包含有该函数原型的头文件即可在程序中直接调用。在前面各章的例题中反复用到的printf(

)、scanf(

)、getchar(

)、putchar(

)、gets(

)、puts(

)等函数均在头文件stdio.h中,sqrt(),fabs(),pow()等函数均在头文件math.h中。②用户定义函数:由用户按需求编写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且还必需在主调函数模块中对该被调函数进展类型阐明,然后才干运用。〔7〕从主调函数和被调函数之间数据传送角度看,函数又可分为无参函数和有参函数两种。〔8〕C言语的函数兼有其他言语中的函数和过程两种功能,从这个角度看,又可把函数分为有前往值函数和无前往值函数两种。6.2.1函数定义C言语函数定义格式如下:[函数前往值的类型名]函数名([类型名方式参数1,类型名方式参数2,…])/*函数头*/{[阐明部分;]/*函数体*/[语句部分;]}其中[]内为可选项。留意:函数名、一对圆括号和花括号不能省!6.2函数的定义和阐明1.无参函数无参函数的普通方式函数前往值的类型名函数名(void){[阐明语句部分;][可执行语句部分;]}例:构造一个输出一行〞*〞的函数:voidprintstar(void){printf(“******************\n〞);}

kj622.有参函数例:编写函数交换2个数;kj63voidswap(inta,intb){inttemp;temp=a;a=b;b=temp;}

不能写成:voidswap(inta,b){inttemp;temp=a;a=b;b=temp;}函数前往值类型函数名参数类型阐明及参数列表6.2.2函数的前往值函数分为有前往值函数和无前往值函数。return语句的格式:return(表达式);或return表达式;或return;功能:1、把return后面“表达式〞的值带给调用函数;2、把控制转向调用函数;格式return;只需功能2例:编写函数,前往2个整数的最大公约数。〔辗转相除法〕kj64intf(intx,inty){intr,t;if(x<y){t=x;x=y;y=t;} while((r=x%y)!=0) {x=y;y=r;}returny;}

留意:(1)声明为void型的函数中不能包括带值的return语句;主函数体内普通不用return语句。(2)当函数没有return语句时,以终了函数的大括号}作为前往点。但这时并不阐明函数没有前往值,这时的前往值是系统给的不确定值。(3)在同一函数内,可根据需求在多处出现return语句,但函数第一次遇到return时就立刻停顿执行,并前往到主调函数;(4)return语句中前往值表达式的类型应该和函数类型一致。假设不一致,那么以函数类型为准,由系统自动进展转换。假设缺省函数类型,那么系一致概按int类型处置。intf(chars1,chars2){if(s1==s2)return1; return0;}kj65

例:计算两数之和#include<stdio.h>doubleadd(doublex,doubley){doubles;s=x+y;returns;}main(){doublea,b,c;a=10.5;b=20.3;c=add(a,b);printf("%lf",add(a,b));add(a,b);}Kj66运转结果为:30.8改成:intadd(doublex,doubley)?6.2.3函数阐明1.函数阐明的方式函数阐明也称为函数声明,运用函数阐明语句可以让C编译程序了解函数前往值类型被调用函数阐明普通格式如下:函数类型函数名(数据类型[参数名1][,数据类型[参数名2]…]);函数阐明语句其实就是函数定义中的函数首部加上分号,这些内容称为函数原型。如:doublemax(doublex,doubley);voidswap(inta,intb);例:计算两数之和#include<stdio.h>main(){doublea,b,c;a=10.5;b=20.3;c=add(a,b);printf("%lf",add(a,b));add(a,b);}doubleadd(doublex,doubley){doubles;s=x+y;returns;}kj67doubleadd(doublex,doubley);doubleadd(doublex,doubley);留意:有三种情况不需阐明:a、函数前往值为整型或字符型;b、被调用函数定义出如今主调函数之前;c、已在一切的函数定义之前〔即文件的开头〕阐明了函数类型。

6.3函数的调用1、调用方式:函数名〔实参表列〕;实参与形参个数相等,类型一致。调用函数时两者按顺序一一对应传送数据。main(){inta=1,b,f(int,int);b=f(a,++a);printf("%d",b);}intf(intx,inty){intz;if(x>y)z=1;elseif(x==y)z=0;elsez=-1;return(z);}例:参数求值顺序main(){inta=1,b,f(int,int);b=f(a,a++);printf("%d",b);}intf(intx,inty){intz;if(x>y)z=1;elseif(x==y)z=0;elsez=-1;return(z);}运转结果:0运转结果:12、调用方式:按函数在程序中出现的位置来分有三种方式。①函数语句。只完成一个操作,并不要求函数带回值。如:printstar();scanf(“%d〞,&a);②函数表达式。出如今表达式中,函数值参与表达式运算。如:c=2*max(a,b);y=x+power(x,3);③函数参数。函数调用作为一个函数的实参。如:m=max(a,max(b,c));printf(“%8.2f\n〞,power(x,3));课堂练习:下面程序的输出结果是〔〕。#include<stdio.h>func(inta,intb){intc;c=a+b;returnc;}main(){intx=6,y=7,z=8,r;r=func((x--,y+=2,x+y),z);printf("%d\n",r);}A.11 B.20 C.21 D.22课堂练习:假设有以下函数调用语句:fun(a+b,(x,y),fun(n+k,d,(a,b)));fun函数参数的个数是A〕3B〕4C〕5D〕66.4函数的参数形参与实参方式参数:定义函数时函数名后面括号中的变量名。实践参数:调用函数时函数名后面括号中的表达式。例:编写程序实现从两整数中求较大数。#include<stdio.h>floatmax(floatx,floaty); /*函数阐明*/main(

){floata,b;floatc;scanf("%f,%f",&a,&b);c=max(a,b); /*调用函数语句,a,b为实参*/printf("a=%f,b=%f\nmax=%f\n",a,b,c);}floatmax(floatx,floaty) /*函数定义,x,y为形参*/{floatz;z=x>y?x:y;printf(“x=%f,y=%f\nz=%f\n〞,x,y,z);return(z);}xy形参ab实参阐明:实参必需有确定的值,形参必需指定类型形参与实参类型一致,个数一样假设形参与实参类型不一致,自动按形参类型转换——函数调用转换值传送方式形参在函数被调用前不占内存;函数调用时,为形参分配单元,并将实参的值复制到形参中;调用终了,形参单元被释放,实参单元仍保管并维持原值特点:形参与实参占用不同的内存单元单向传送例:计算x的立方#include<stdio.h>floatcube(floatx){return(x*x*x);}main(){floata,product;scanf("%f",&a);product=cube(a);printf(〞%.4f%.4f\n",a,product);}xaproduct××××1.21.21.7281030x:y:调用前:调用终了:1030x:y:例:交换两个数#include<stdio.h>main(){intx=10,y=30;printf("%d,%d\n",x,y);printf("swapped:\n");swap(x,y);printf("%d,%d\n",x,y);}swap(inta,intb){inttemp;temp=a;a=b;b=temp;}调用:1030a:b:1030x:y:swap:1030x:y:3010a:b:temp普通函数调用main()调用函数a终了a函数执行2134566.5函数的嵌套调用和递归调用6.5.1函数的嵌套调用函数的嵌套调用是指,在执行被调用函数时,被调用函数又调用了其它函数。这与其它言语的子程序嵌套调用的情形是类似的,其关系可表示如右图所示。例:求三个数中最大数和最小数的差值intmax(intx,inty,intz)/*定义函数max求x,y,z中最大值*/{intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz)/*定义函数min,求x,y,z中最小值*/{intr;r=x<y?x:y;return(r<z?r:z);}intdif(intx,inty,intz) /*定义函数dif*/{returnmax(x,y,z)-min(x,y,z); /*嵌套调用*/}voidmain(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);d=dif(a,b,c); /*调用函数dif*/printf("Max-Min=%d\n",d);}假设输入2、3,求以下程序的运转结果,分析嵌套调用的执行过程。#include<stdio.h>intf(intn){intrtn=0;inti;for(i=1;i<=n;i++)rtn*=i;return(rtn);}longsum(inta,intb){longc1,c2;c1=f(a);c2=f(b);return(c1+c2);}main(){intn1=5,n2=10,a;a=sum(n1,n2);printf("a=%d",a);}6.5.2函数的递归调用在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。递归调用方式如下:(1)直接递归voida(){...…a();/*本人调用本人,直接递归*/...…}函数a()

调用函数a()(2)间接递归voida(){...…b();/*调用函数b*/...…}voidb(){......a();/*调用函数a,间接递归*/……}

调b调aa()b()以上是无终止的函数调用,因此,一个正确的递归调用的函数必需满足以下条件:1、一个问题转化成一个新问题,解题方法类似,只是所处置的对象的值有规律的递增或递减。2、可以运用这个转换过程使问题得到处理。3、必需有明确的终了递归的条件;分析问题2种方法:递推和递归递推:从一个知的现实出发,按一定的规律推出下一个现实。通常利用迭代公式法,经过循环构造实现,循环的终值是问题的结果。递归:从要求的结果出发,归纳出后一个结果和前一个结果存在的关系,直到一个知值为止〔即反推法〕。通常设计函数〔递归函数〕,不断运用下一级值调用本身,直到一个知的值〔递归出口〕。0!=11!=0!*1…………….n!=(n-1)!*n例:求n的阶乘n!递推公式:1n=0sn=sn-1*nn>0程序段为:#include<stdio.h>main(){intm=1,i,n;scanf("%d",&n);for(i=1;i<=n;i++)m=m*i;printf("theresultis%10d",m);}例:求n的阶乘n!递归方法求n!由于n!=n*(n-1)!是递归定义所以求n!〔n-1〕!

(n-1)!〔n-2〕!

(n–2)!〔n-3〕!

……

1!0!的问题,

知条件为:0!=1。

递归函数:1n=0f(n)=f(n-1)*nn>0递归函数普通方式:函数名f〔参数〕{if〔n==初值〕结果=….;else结果=含f(n-1)的表达式;return(前往结果);}#include<stdio.h>intf(intx){intt;if(x==0)t=1;/*递归出口*/elset=f(x-1)*x;;/*递归公式*/return(t);}main(){intn=0,s;scanf("%d",&n);s=f(n);printf("%d!=%10d",n,s);}f函数在回推阶段被调用了4次,递归调用了3次,到终止条件才有确定的值,然后再递推出每一次调用的值,最后得到所求的结果。例:求Fibonacci数列:打印1,1,2,3,5,8,……的前40个数。#include<stdio.h>main(){longf1,f2;inti;f1=1;f2=1;for(i=1;i<20;i++){printf("%12ld%12ld",f1,f2);if(i%2==0)printf("\n");f1=f1+f2;f2=f2+f1;}}方法1:用循环构造来实现#include<stdio.h>intfib(intn){intf; if(n==1||n==2)f=1; elsef=fib(n-1)+fib(n-2); returnf;}main(){inti;for(i=1;i<=40;i++){printf("%15d",fib(i));if(i%4==0) printf("\n");}}方法2:用递归函数来实现例:反向输出一个整数#include<stdio.h>main(){intn; scanf("%d",&n); if(n<0) {n=-n; printf("-"); } while(n!=0) {printf("%d",n%10); n=n/10; }}方法1:用循环构造来实现#include<stdio.h>voidmain(){voidprintn(intx);intn;scanf("%d",&n);if(n<0){ n=-n;putchar('-'); }printn(n);}voidprintn(intx) /*反向输出整数x*/{if(x>=0&&x<=9) /*假设x为一位整数*/printf("%d",x); /*那么输出整数x*/else /*否那么*/{ printf("%d",x%10); /*输出x的个位数字*/ printn(x/10);/*将x中的个位数字去掉,构成新的x后,继续递归操作*/}}方法2:用递归函数来实现输出一个正整数的递归算法为:if(n为一位整数) 输出n; else {输出n的个位数字; 对剩余数字组成的新整数反复"反向输出"操作; }例:汉诺塔问题。

初始形状:有3个塔,每个都堆放假设干个盘子。开场时,一切盘子均在塔a上,并且,盘子从上到下,按直径增大的次序放置。要求处理问题:设计一个盘子挪动的序列,使得塔a上的一切盘子借助于塔b挪动到塔c上。两个限制:1〕一次只能挪动一个盘子;2〕任何时候都不能把盘子放在比它小的盘子的上面。

假设塔a有n个盘子知条件:假设只需一个盘子,那么是直接从1移到3〔递归出口〕算法设计如下:第一步:把n-1个盘子按照标题中的规那么从塔a〔源塔〕借助于塔c〔中间塔〕搬到塔b〔目的塔〕。第二步:将剩下的一只盘〔也就是最大的一只〕直接从塔a〔源塔〕搬到那个依然空着的塔c〔目的塔〕。第三步:再次将b塔〔源塔〕上的n-1个盘子借助于塔a〔中间塔〕搬到塔c〔目的塔〕。这一步是没有问题的,由于c塔上仅有一只最大的盘。函数hanoi(intn,inta,intb,intc)设计:1.假设(n==1)那么ac;2.否那么执行3步2-1调用函数hanoi(n-1,a,c,b);2-2ac;2-3调用函数hanoi(n-1,b,a,c);例Hanoi问题#include<stdio.h>voidhanoi(intn,inta,intb,intc){if(n==1)printf("%d->%d\n",a,c);else{hanoi(n-1,a,c,b); printf("%d->%d\n",a,c); hanoi(n-1,b,a,c);}}main(){intn;printf("Inputn:");scanf("%d",&n);hanoi(n,1,2,3);}

运转情况如下:inputn:3↙thestep:1-->31-->23-->21-->32-->12-->31-->3先看一个例子,错在那里?:#include"stdio.h"voidf1(){intt=2;a*=t;b/=t;}main(){inta,b;scanf("%d,%d",&a,&b);f1();//调用函数f1()printf("a=%d,b=%d",a,b);}1编译程序会提示出错:Undefinedsymbol‘a’和Undefinedsymbol‘b’。为什么?6.6变量的存储类型6.6.1变量的生存期和作用域生存期:变量在某一时辰存在-------静态变量与动态变量作用域:变量在某区域内有效-------部分变量与全局变量(文件、函数、复合语句)6.6.2变量的存储类型(特性)1.c言语中每一个变量有两个属性:数据类型,存储类型。完好的变量定义:[存储类型][数据类型]变量名;2.变量的存储类型(特性)自动型auto静态型static存放器型register外部型extern程序区静态存储区动态存储区2.静态存储类型的变量的生存期为程序执行的整个过程,在该过程中占有固定的存储空间,称它们为永久存储。staticextern动态存储类型变量只生存在某一段时间内。例如,函数的形参和函数体内定义的变量,只是在程序进入该函数时才分配存储空间,当该函数执行完后,变量对应的存储空间又被撤销了。atuoregister部分变量与全局变量部分变量---内部变量定义:在函数内或复合语句定义阐明:main〔函数〕中定义的变量只在main〔函数〕中有效。复合语句中定义的变量只在复合语句中有效。不同函数中同名变量,占不同内存单元。形参属于部分变量。部分变量可用存储类型:autoregister。static〔默以为auto〕floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}main(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效#include<stdio.h>sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}main(){autointa,b;a=3;b=4;sub();printf("main:a=%d,b=%d\n",a,b);}31.自动变量部分静态变量值具有可承继性部分静态变量的初始化只在编译时进展一次,每次调用他们所在的函数时,不再重新赋初值;如定义但不初始化,自动赋0或‘\0’1.静态部分变量static数据类型变量名staticinti=1;#include<stdio.h>main(){voidin(void);in();in();in();}voidin(void){intx=0;x++;printf(“%d\n〞,x);}4运转结果:111#include<stdio.h>main(){voidin(void);in();in();in();}voidin(void){staticintx=0;x++;printf(“%d\n〞,x);}5运转结果:1231.静态部分变量例:分析执行结果f(inta){intb=0;staticintc=3;b++;c++;printf("%5d%5d%5d\n",a,b,c);return(a+b+c);}main(){inta=2,k;for(k=0;k<3;k++)printf("%5d\n",f(a));}6静态变量只初始化一次结果:214〔a,b,c)7(f(a))21582169(3)register(存放器)型将运用频率高的变量定义为register型,可以提高运转速度。存放器变量只限于整型、字符型、指针型的部分变量。存放器变量是动态变量,而且数目有限,普通仅允许阐明两个存放器变量,过多的存放器变量的编译器能够把它看成Auto类型。例如:registerintd;registercharc;全局变量---外部变量定义:在函数外定义,可为本文件一切函数共用有效范围:从定义变量的位置开场到根源文件终了,及有extern阐明的其它源文件外部变量阐明:外部变量定义与外部变量阐明不同假设外部变量与部分变量同名,那么外部变量被屏蔽外部变量可用存储类型:缺省或static#include<stdio.h>externinta,b;voidswap(){intt;t=a;a=b;b=t;printf(“swap:a=%d,b=%d\n〞,a,b);}inta,b;main(){printf(“Entera,b:〞);scanf(“%d,%d〞,&a,&b);swap();printf(“main:a=%d,b=%d〞,a,b);}7Entera,b:5,3↙swap:a=3,b=5main:a=3,b=5运转结果全局变量有两个问题:其一:当全局变量定义在后,援用它的函数在前时,如何运用该全局变量?这就需求把该全局变量的作用域延伸至该函数;其二:能否使在某文件中定义的全局变量,在其它文件中无须再次定义而直接运用它呢?这就需求把全局变量的作用域进展延伸。C言语可经过外部变量阐明到达此目的。定义阐明次数:只能1次可阐明多次位置:一切函数之外函数内或函数外分配内存:分配内存,可初始化不分配内存,不可初始化外部变量阐明:extern数据类型变量表;外部变量定义与外部变量阐明不同假设外部变量与部分变量同名,那么外部变量被屏蔽例外部变量定义与阐明运转结果:max=13#include<stdio.h>externinta,b;//外部变量阐明intmax(intx,inty);//函数阐明main(){printf("max=%d",max(a,b));}inta=13,b=-8;//外部变量定义intmax(intx,inty)//函数定义{intz;z=x>y?x:y;return(z);}#include<stdio.h>inta=7,b=9;//a,b为全局变量voidf1(intx){intt1;t1=b*x;printf("f1:t1=%d,a=%d,b=%d\n",t1,3*a,3*b);}main(){f1(2);//调用函数f1()printf("main:a=%d,b=%d\n",a,b);}t8#include<stdio.h>inta,b;/*a,b为全局变量*/voidf1(intx){intt1,a;//重新定义a,没重新定义b,a值传不过去。a=x*4;t1=b*3;b=10;printf("f1:t1=%d,a=%d,b=%d\n",t1,a,b);}main(){a=2;b=4;/*此a,b是全局变量,赋值*/f1(2);/*调用函数f1()*/printf("main:a=%d,b=%d",a,b);}9f1:t1=12,a=8,b=10main:a=2,b=10结论:全局变量与部分变量同名时,部分变量起作用,全局变量被屏蔽〔不影响〕变量存储类型小结静态动态存储方式程序整个运转期间函数调用开场至终了生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区存放器部分变量外部变量作用域定义变量的函数或复合语句内本文件其它文件部分变量默以为auto型register型变量个数受限,且不能为long,double,float型部分static变量具有全局寿命和部分可见性部分static变量具有可承继性extern不是变量定义,可扩展外部变量作用域register部分staticauto外部static外部存储类别6.7内部函数、外部函数C言语根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。6.7.1内部函数〔又称静态函数〕假设一个函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,那么称为内部函数。定义一个内部函数,只需在函数类型前再加一个“static〞关键字即可,定义格式如下:static函数类型函数名(函数参数表){……}如staticintfun(a,b,c){……}6.7.1外部函数在定义函数时,假设没有加关键字“static〞,或者冠以“extern〞,那么表示此函数是外部函数,其定义格式为:[extern]函数类型函数名(函数参数表){……}调用外部函数时,必需对被调用的外部函数进展阐明。例/*FILE1*/#include<stdio.h>inti;/*在FILE1中定义外部变量i*/voidfunc();/*外部函数阐明*/main(){ i=5; printf("file1:%d\n",i); func();}/*FILE2*/externinti;/*外部变量阐明,FILE2援用FILE1中定义的外部变量i*/voidfunc(){ printf("file2:%d\n",i);}该程序的运转结果是:file1:5file2:56.8编译预处置“编译预处置〞是C言语编译系统的一个组成部分。是在编译前由编译系统中的预处置程序对源程序的预处置命令进展加工。源程序中的预处置命令均以“#〞开头,终了不加分号,以区别源程序中的语句,它们可以写在程序中的任何位置,作用域是自出现点到源程序的末尾。预处置命令包括执行宏定义(宏交换)、包含文件和条件编译。一.宏定义简单宏定义1.普通方式为:#define宏名串(宏体)如:#definePI3.14159/*定义后,可以用PI来替代串3.14159*/2.宏定义的作用在宏定义之后,该程序中宏名就代表了该字符串。阐明:占单独书写行语句尾不加分号3.阐明①可以用#undef命令终止宏定义的作用域。例如:#undefPI②宏定义的嵌套运用#defineR3.0#definePI3.1415926#defineL2*PI*R/*宏体是表达式*/#defineSPI*R*Rmain(){printf("L=%f\nS=%f\n",2*PI*R,PI*R*R);/*2*PI*R交换L,PI*R*R交换S*/}t6-1程序运转结果如下:L=18.849556S=28.274333③双引号内与宏同名的字母不作宏展开.main(){printf("L=%f\nS=%f\n",L,S);}t6-1#defineX5#defineYX+1#defineZY*X/2main(){inta=Y;printf("%d\n",Z);printf("%d\n",--a);}t6-2//Z=Y*X/2=5+1*5/2=7运转结果:75带参数的宏定义1.带参数的宏定义的普通方式为#define宏名(参数表〕字符串#defineS(a,b)((a)*(b))2.带实参的宏名被展开宏名被所定义的宏体交换,宏体中的形参按从左到右的顺序被实参交换。例如:area=S(3,2);展开为:area=((3)*(2));宏体及各形参外普通应加括号〔〕

普通写成:#definePOWER(x)((x)*(x))x=4;y=6;z=POWER(x+y);宏展开:z=((x+y)*(x+y));例#definePOWER(x)x*xx=4;y=6;z=POWER(x+y);宏展开:z=x+y*x+y;结果为:100结果为:34课堂练习:#include<stdio.h>#defineMIN(x,y)(x)<(y)?(x):(y)main(){inti,j,k;i=10;j=15;k=10*MIN(i,j);printf("%d\n",k);}A)15B)100C)10D)150//10*i<j?10*10<15?(10):(15)运用宏交换应留意的问题(1)宏名与宏体之间用空格相隔,宏名和参数之间不能有空格;如有宏定义:#definef(x)((x)–1)/*宏名f(x)中有空格*/(2)宏名虽然是字符串,但不能用引号括起来(3)在宏定义中结尾不能有分号〞;〞(4)宏定义中的参数尽量用圆括号括起来以免错误.(5)较长的宏定义在一行中写不下时,要在本行结尾运用反斜杠表示续行。如:#defineOUTPUTprintf(“Thisisaninteresting\programwhichteachespepolehowtousedefine\command〞)t6-3这是比较特殊的,由于在C言语中普通情况下不需求有续行的标识,而预处置是个例外。(6)宏定义可以写在程序中的任何地方,但因其作用域为从定义之处到文件未尾,所以一定要写在程序援用该宏之前,通常写在一个文件之首。#defineMAX(x,y)(x)>(y)?(x):(y)…….main(){inta,b,c,d,t;…….t=MAX(a+b,c+d);……}t6-4宏展开:t=(a+b)>(c+d)?(a+b):(c+d);例用宏定义和函数实现同样的功能intmax(intx,inty){r

温馨提示

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

评论

0/150

提交评论