




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
C語言程序設計
函數8.1函數定義
8.2函數參數和返回值
8.2.1形式參數和實際參數
8.2.2函數返回值
8.3函數調用
8.3.1調用方式
8.3.2函數說明
8.3.3函數嵌套調用
8.3.4函數遞歸調用
8.4數組作為函數參數
8.5局部變量和全局變量
8.5.1局部變量
8.5.2全局變量
8.6存儲類型
8.6.1auto存儲類型
8.6.2extern存儲類型
8.6.3register存儲類型
8.6.4static存儲類型8.7內部函數和外部函數
C語言不僅提供了極為豐富的庫函數(如TurboC,MSC都提供了三百多個庫函數),還允許用戶建立自己定義的函數。用戶編寫一個個相對獨立的函數模塊算法,然后用調用的方法來使用函數。例8-1帶參函數程序main(){inta,b,c;scanf(“%d,%d”,&a,&b);c=fun(a,b);printf(“funis%d”,c);}fun(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}說明:(1)一個源程序文件由一個或多個函數組成。一個源程序文件是一個編譯單位,即以源文件為單位進行編譯,而不是以函數為單位進行編譯。(2)一個C語言程序由一個或多個源程序文件組成。對于較大的程序,一般不希望全放在一個文件中,而是將函數和其他內容(如預編譯命令)分別放到若干個源文件中,再由若干個源文件組成一個C語言程序。這樣可以分別編寫、分別編譯,提高調試效率。一個源文件可以為多個C語言程序共用。(3)C語言程序的執(zhí)行從main函數開始,調用其它函數后流程回到main函數,在main函數中結束整個程序的運行。(4)所有函數都是平行的,即在定義函數時是相互獨立的,一個函數并不從屬于另一個函數,即函數不能嵌套定義,但可以相互調用,甚至嵌套調用、遞歸調用(不能調用main函數)。
(5)從用戶使用角度看,函數有兩種?!駱藴屎瘮担磶旌瘮?。這是由系統(tǒng)提供的,用戶無須定義,也不必在程序中作類型說明,只需在程序前包含有該函數原型的頭文件即可在程序中直接調用?!裼脩糇约憾x的函數,以解決用戶的專門需要。(6)從函數的形式看,函數分兩類?!駸o參函數。在調用無參函數時,主調函數并不將數據傳送給被調用函數,一般用來執(zhí)行指定的一組操作。無參函數可以帶回也可以不帶回函數值,但一般以不帶回函數值居多?!裼袇⒑瘮?。在調用函數時,在主調函數和被調函數之間有參數傳遞,也就是說,主調函數可以將數據傳給被調函數使用,被調用函數中的數據也可以帶回來供主調函數使用。8.1函數的定義1.函數的定義(1)無參函數的一般形式類型說明符函數名(){類型說明;語句;}(2)有參函數的一般形式
類型說明符函數名(形式參數表){類型說明;
語句;}voidHello(){printf("Hello,world\n");}intmax(a,b)inta,b;{if(a>b)returna;elsereturnb;}8.2.1形式參數和實際參數
函數的形參和實參具有以下特點:1.形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元,因此,形參只有在函數內部有效。函數調用結束返回主調函數后則不能再使用該形參變量。2.實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值,以便把這些值傳送給形參。3.實參和形參在數量上、類型上、順序上應嚴格一致,否則會發(fā)生“類型不匹配”的錯誤。4.函數調用中發(fā)生的數據傳送是單向的。即只能把實參的值傳送給形參,而不能把形參的值反向地傳送給實參,因此在函數調用過程中,形參的值發(fā)生改變,而實參中的值不會變化。8.2函數參數和返回值
例8-3求兩整數中的較大值。#include<stdio.h>intmax(inta,intb);voidmain(){ inta,bmax; printf("輸入兩整數:"); scanf("%d%d",&a,&b); max=max(a,b);/*調用max函數,在表達式中出現*/ printf("\n兩整數中的較大值是%d\n",max);}intmax(inta,intb)/*求兩整數中的較大值函數定義*/{ if(a>b)returna; elsereturnb;}函數的值是指函數被調用之后,執(zhí)行函數體中的程序段所取得的并返回給主調函數的值,這就是函數的返回值。說明:(1)函數的值只能通過return語句返回主調函數。return語句的一般形式為:
return表達式;
return(表達式);return;該語句的功能是計算表達式的值,并返回給主調函數。在函數中允許有多個return語句,但每次調用只能有一個return語句被執(zhí)行,因此只能返回一個函數值。8.2.2函數返回值
(2)函數值得類型。既然函數可以有返回值,這個值當然應屬于某一個確定的類型,應當在定義函數時指定函數值的類型。例如:intmax(inti,inty)charletter(charc1,charc2)floatf(floatx)doublemin(doublex,doubley)C語言還規(guī)定,凡不加類型聲明的函數,一律自動按整型處理。(3)函數值的類型和函數定義中函數的類型應保持一致。如果兩者不一致,則以函數類型為準,自動進行類型轉換。(4)不返回函數值的函數,可以明確定義為“空類型”,類型說明符為“void”。voids(intn){…}一旦函數被定義為空類型后,就不能在主調函數中使用被調函數的函數值了。例如,在定義s為空類型后,在主函數中寫下述語句sum=s(n);就是錯誤的。為了使程序有良好的可讀性并減少出錯,不要求返回值的函數都應定義為空類型。函數調用的一般形式為
被調用函數名([參數表達式1,參數表達式2,…,參數表達式n]);其中,參數前不加數據類型說明,參數表達式可以是常量、變量或表達式。各個參數表達式之間用逗號分割。參數表示式的個數與該函數定義時形式參數的個數、數據類型都應該匹配,否則會出現預料不到的結果。如果被調用函數是無參函數,即[]中沒有內容時,函數名后面的括號不要省略。使用C語言的庫函數就是函數簡單調用的方法。例如:
main()
{
printf(“******\n”);
}8.3函數調用
8.3.1調用方式
(1)函數表達式
函數作為表達式中的一項出現在表達式中,以函數返回值參與表達式的運算。這種方式要求函數有返回值。例如:
z=max(x,y)*8;其中,函數max是賦值表達式的一部分,它的值乘以8后在賦予變量z(2)函數語句函數調用的一般形式加上分號即構成函數語句。例如:
printf(“%d”,m);
max(x,y);等都是以函數語句的方式調用函數。(3)函數實參函數作為另一個函數調用的實際參數出現。這種情況是把該函數的返回值作為實參傳遞給調用函數,因此要求該函數必須有返回值。例如:
printf(“%d”,max(m,n));上述語句是把max函數的返回值又作為printf函數的實參來使用。對被調函數的說明也有兩種格式,一種為傳統(tǒng)格式。其格式為:類型說明符被調函數名();這種格式只給出函數返回值的類型,被調函數名及一個空括號。這種格式由于在括號中沒有任何參數信息,因此不便于編譯系統(tǒng)進行錯誤檢查,容易發(fā)生錯誤。另一種為現代格式,其一般形式為:類型說明符被調函數名(類型形參,類型形參…);
或為:類型說明符被調函數名(類型,類型…);
現代格式的括號內給出了形參的類型和形參名,或只給出形參類型。這便于編譯系統(tǒng)進行檢錯,以防止可能出現的錯誤。max函數的說明若用傳統(tǒng)格式可寫為:intmax();用現代格式可寫為:intmax(inta,intb);或寫為:intmax(int,int);8.3.2函數說明
注意:(1)被調用的函數必須是已經存在的函數(是庫函數或用戶自己定義的函數)(2)在調用系統(tǒng)函數時,需要用包含命令#include“頭文件名.h”將定義系統(tǒng)函數的庫文件包含在本程序中,有關包含命令的相關知識在后面章節(jié)中詳細介紹。(3)如果調用函數和主函數在一個編譯單元中,則在書寫順序上被調用函數比主函數先出現;或者被調用函數雖然在主函數之后出現,而被調用函數的數據類型是整型或字符型,可以不對被調函數加以說明,除了上述兩種情況以外,都要對被調用函數加以說明。函數的原型說明8.3.3函數嵌套調用
例8-5用以下近似公式編程計算ex的值,ex=1+x+x2/2!+x3/3!+…(前20項的和)。#include<stdio.h>floatf2(intn) {if(n==1)return1;elsereturn(f2(n-1)*n);}floatf1(intx,intn){inti;floatj=1;for(i=1;i<=n;i++)j=j*x;returnj;}voidmain(){floatexp=1.0;intn,x;printf(“Inputanumber:”);scanf(“%d”,&x);printf(“%\n”,x);exp=exp+x;for(n=2;n<=19;n++)exp=exp+f1(x,n)/f2(n);printf(“\nTheisexp(%d)=%8.4f\n”,x,exp);}一個函數在它的函數體內調用它自身稱為遞歸調用。這種特殊的函數稱為遞歸函數。遞歸調用有兩種:直接遞歸調用和間接遞歸調用。8.3.4函數遞歸調用
例8-6用遞歸法計算n!。#include<stdio.h>longff(intn){longf;if(n<0)printf("n<0,inputerror");elseif(n==0||n==1)f=1;elsef=ff(n-1)*n;return(f);}voidmain(){intn;longy;printf("\ninputainteagernumber:\n");scanf("%d",&n);y=ff(n);printf("%d!=%ld",n,y);}例8-7Hanoi塔問題。一塊板上有三根針,A,B,C。A針上套有64個大小不等的圓盤,大的在下,小的在上。要把這64個圓盤從A針移動C針上,每次只能移動一個圓盤,移動可以借助B針進行。但在任何時候,任何針上的圓盤都必須保持大盤在下,小盤在上。求移動的步驟:#include<stdio.h>move(intn,intx,inty,intz){if(n==1)printf("%c-->%c\n",x,z);else{move(n-1,x,z,y);printf("%c-->%c\n",x,z);move(n-1,y,x,z);}}voidmain(){inth;printf("\ninputnumber:\n");scanf("%d",&h);printf("thesteptomoving%2ddiskes:\n",h);move(h,'a','b','c');}
數組名能作為函數的形參,但不能作為函數的返回值類型。數組名作為實參時是傳遞數組首地址。形參數組實質是一個指針變量,占2字節(jié),存實參數組的首地址。傳址(傳地址值)是C函數參數傳遞的第二種方法,效率高,用途廣;但難度比傳值(傳數據值)大。8.4數組作為函數參數
2.數組名作為函數參數例8-8一維數組的數組元素值減2。#include<stdio.h>#defineN5 voidadd1(intx[],intn);voidmain(){inta[N]={6,7,8,9,10},i;printf("數組A[%d]:\n",N);for(i=0;i<N;i++)printf("a[%d]:%x%5d\n",i,&a[i],a[i]);add1(a,N);printf("\n數組A[%d:\n",N);for(i=0;i<N;i++)printf("a[%d]:%x%5d\n",i,&a[i],a[i]);}voidadd1(intx[],intn) {inti;printf("x中的值(地址):%x\n",x);printf("數組x[%d]:\n",n);for(i=0;i<n;i++)printf("x[%d]:%x%5d\n",i,&x[i],x[i]);for(i=0;i<n;i++) x[i]=x[i]-2;}例8-9有一個一維數組score,內放10個學生成績,求平均成績。#include<stdio.h>floataverage(floatarray[10]);voidmain(){floatscore[10],aver;inti;printf(“input10scores:\n”);for(i=0;i<10;i++)scanf(“%f”,&score[i]);printf(“\n”);aver=average(score);printf(“averagescoreis%5.2f”,aver);}floataverage(floatarray[10]){inti;floataver,sum=array[0];for(i=1;i<10;i++)sum=sum+array[i];aver=sum/10;return(aver);}局部變量也稱為內部變量。局部變量是在函數內作定義說明的。它只在該函數范圍內有效。也就是說,只有在包含變量說明的函數內部,才能使用被說明的變量,在此函數之外就不能使用這些變量了,離開該函數后再使用這種變量是非法的。例如:intf1(inta)/*函數f1*/{intb,c;……}a、b、c作用域。intf2(intx)/*函數f2*/{inty,z;}x、y、z作用域。voidmain(){intm,n;}m、n作用域。8.5局部變量和全局變量
8.5.1局部變量
關于局部變量的作用域還要說明以下幾點:(1)主函數main()中定義的變量,也只能在主函數中使用,其它函數不能使用。同時,主函數中也不能使用其它函數中定義的變量。因為主函數也是一個函數,與其它函數是平行關系。這一點是與其它語言不同的,應予以注意。(2)形參變量也是內部變量,屬于被調用函數;實參變量,則是調用函數的內部變量。(3)允許在不同的函數中使用相同的變量名,它們代表不同的對象,分配不同的單元,互不干擾,也不會發(fā)生混淆。(4)在復合語句中也可定義變量,其作用域只在復合語句范圍內。第8章函數8.5局部變量和全局變量例8-10定義變量的作用域。inta,b;/*外部變量*/voidf1()/*函數f1*/{……}floatx,y;/*外部變量*/intfz()/*函數fz*/{……}voidmain()/*主函數*/{……}/*全局變量x、y作用域,全局變量a、b作用域*/8.5.2全局變量
例8-11有一個一維數組,內放10個學生成績,寫一個函數,求出平均分,最高分和最低分。#include<stdio.h>floatMax,Min;floataverage(floatarray[],intn){inti;floataver,sum=array[0];Max=Min=array[0];for(i=1;i<n;i++){if(array[i]>Max)Max=array[i];elseif(array[i]<Min)Min=array[i];sum=sum+array[i];}aver=sum/n;return(aver);}voidmain(){floatave,score[10];inti;for(i=0;i<10;i++)scanf("%f",&score[i]);ave=average(score,10);printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",Max,Min,ave);}對于全局變量還有以下幾點說明:
(1)外部變量可加強函數模塊之間的數據聯系,但降低這些函數的獨立性。
(2)在同一源文件中,允許外部變量和內部變量同名。在內部變量的作用域內,外部變量將被屏蔽而不起作用。
(3)外部變量的作用域是從定義點到本文件結束。如果定義點之前的函數需要引用這些外部變量時,需要在函數內對被引用的外部變量進行說明。外部變量說明的一般形式為:extern數據類型
外部變量[,外部變量2……];注意:外部變量的定義和外部變量的說明是兩回事。外部變量的定義,必須在所有的函數之外,且只能定義一次。而外部變量的說明,出現在要使用該外部變量的函數內,而且可以出現多次。
#include<stdio.h>voidtestauto();voidmain(){inti;for(i=0;i<4;i++)testauto();printf("\n");}/*測試自動類局部變量的特性*/voidtestauto(){autointva=0;/*或intva=0;*/printf("%d”,va);va++;/*值不保留*/}自動變量的類型說明符為auto。這種存儲類型是C語言程序中使用最廣泛的一種類型。C語言規(guī)定,函數內凡未加存儲類型說明的變量均視為自動變量。例8-12測試自動類型局部變量的特性。8.6.1auto存儲類型
8.6存儲類型
自動變量具有以下特點:(1)自動變量的作用域僅限于定義該變量的區(qū)域內。在函數中定義的自動變量,只在該函數內有效。在復合語句中定義的自動變量只在該復合語句中有效。
例如:intkv(inta){autointx,y;{autocharc;}/*c的作用域*/……}/*a、x、y的作用域*/(2)自動變量屬于動態(tài)存儲方式,只有在定義該變量的函數被調用時才給它分配存儲單元,開始它的生存期。函數調用結束,釋放存儲單元,結束生存期。因此函數調用結束之后,自動變量的值不能保留。在復合語句中定義的自動變量,在退出復合語句后也不能再使用,否則將引起錯誤。例8-13變量的作用域----自動變量。voidmain(){autointa,s=1,p=2; printf("\ninputanumber:\n");scanf("%d",&a);if(a>0){autos,p;s=a+a;p=a*a;}printf("s=%dp=%d\n",s,p);}(3)由于自動變量的作用域和生存期都局限于定義它的個體內(函數或復合語句內),因此不同的個體中允許使用同名的變量而不會混淆。即使在函數內定義的自動變量也可與該函數內部的復合語句中定義的自動變量同名。外部變量的幾個特點:(1)外部變量和全局變量是對同一類變量的兩種不同角度的提法。全局變量是從它的作用域提出的,外部變量從它的存儲方式提出的,表示了它的生存期。(2)當一個源程序由若干個源文件組成時,在一個源文件中定義的外部變量在其它的源文件中也有效。例如F1.C:inta,b;/*外部變量定義*/charc;/*外部變量定義*/voidmain(){……}F2.C:externinta,b;/*外部變量說明*/externcharc;/*外部變量說明*/func(intx,y){……}8.6.2extern存儲類型
寄存器變量存放在CPU的寄存器中,使用時,不需要訪問內存,而直接從寄存器中讀寫,這樣可提高效率。變量的作用域----寄存器變量。#include<stdio.h>voidmain(){registerk,sum=0;for(k=1;k<=1000;k++)sum=sum+k;printf("sum=%d\n",sum);}8.6.3register存儲類型
1.靜態(tài)局部變量在局部變量的說明前再加上static說明符就構成靜態(tài)局部變量。例如:staticinta,b;staticfloatarray[5]={1,2,3,4,5};靜態(tài)局部變量屬于靜態(tài)存儲方式,它具有以下特點:(1)靜態(tài)局部變量在函數內定義,但不象自動變量那樣,當調用時就存在,退出函數時就消失。靜態(tài)局部變量始終存在著,也就是說它的生存期為整個源程序。(2)靜態(tài)局部變量的生存期雖然為整個源程序,但是其作用域仍與自動變量相同,即只能在定義該變量的函數內使用該變量。退出該函數后,盡管該變量還繼續(xù)存在,但不能使用它。(3)允許對構造類靜態(tài)局部量賦初值。(4)對基本類型的靜態(tài)局部變量若在說明時未賦以初值,則系統(tǒng)自動賦予0值。8.6.4static存儲類型靜態(tài)變量的作用域。#include<stdio.h>voidmain(){inti;voidf();/*函數說明*/for(i=1;i<=10;i++)f();/*函數調用*/}voidf()/*函數定義*/{staticintj=0;++j;printf("%d\n",j);}2.靜態(tài)全局變量在函數外部定義變量時,用static修飾的變量是靜態(tài)類全局變量。它分配在數據區(qū),作用范圍也是從定義點開始到該文件結束,或稱為文件作用域;但只限于該源文件,不能被其它源文件引用。靜態(tài)類全局變量在執(zhí)行main之前初始化;未初始化,其值為0。
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度特色木門安裝與文化創(chuàng)意設計合同
- 二零二五年度全新版3號海上貨物快速運輸服務合同
- 慶六一活動方案模板
- 登山活動方案
- 臨床病理復試題目答案2025版
- 高校生體育活動競賽策劃稿和方案
- 小學生八一建軍節(jié)活動方案
- 4.3免疫失調課件-高二上學期生物人教版選擇性必修
- 中秋節(jié)中隊班會課件
- 工程檔案分類編號規(guī)范方案
- 2025年省國有資本運營控股集團有限公司人員招聘筆試備考試題及答案詳解(名校卷)
- 2025年輔警招聘考試試題庫完整答案
- 宿州蕭縣鄉(xiāng)鎮(zhèn)事業(yè)單位招聘考試真題2024
- 2025至2030全球及中國近炸引信傳感器行業(yè)項目調研及市場前景預測評估報告
- 部編版三年級語文上冊 寫字表
- 工廠十周年活動策劃方案
- 黑啟動操作培訓課件
- 天津匯融商業(yè)管理有限公司招聘筆試題庫2025
- 腫瘤的健康科普
- 廣東教育學院德育研究中心
- 2025至2030中國清潔機器人市場經營效益與投融資發(fā)展狀況報告
評論
0/150
提交評論