二級語言函數(shù)_第1頁
二級語言函數(shù)_第2頁
二級語言函數(shù)_第3頁
二級語言函數(shù)_第4頁
二級語言函數(shù)_第5頁
已閱讀5頁,還剩78頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

二級語言函數(shù)第一頁,共八十三頁,編輯于2023年,星期五2023/5/231學習目標庫函數(shù)的正確調用函數(shù)的定義方法函數(shù)的類型和返回值形式參數(shù)與實際參數(shù),參數(shù)值的傳遞函數(shù)的正確調用,嵌套調用,遞歸調用局部變量和全局變量變量的存儲類別(自動,靜態(tài),寄存器,外部),變量的作用域和生存期內部函數(shù)與外部函數(shù)第二頁,共八十三頁,編輯于2023年,星期五2023/5/232在C語言程序設計中,具有特定功能的子模塊對應為“函數(shù)”;函數(shù)是一個命名的程序段,負責完成特定的、相對獨立的動作或計算第三頁,共八十三頁,編輯于2023年,星期五2023/5/2337-1概述【例7-1】程序示例。

main(){inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("maxis%d",c);}max(intx,inty){intz;z=x>y?x:y;return(z);}運行時輸入9,4結果為:

maxis9第四頁,共八十三頁,編輯于2023年,星期五2023/5/2347-1概述(1)一個源程序文件由一個或多個函數(shù)組成。一個源程序文件是一個編譯單位,即以源文件為單位進行編譯,而不是以函數(shù)為單位進行編譯。第五頁,共八十三頁,編輯于2023年,星期五2023/5/2357-1概述(2)一個C程序由一個或多個源程序文件組成。對于較大的程序,一般不希望全放在一個文件中,而將函數(shù)和其它內容(如預編譯命令)分別放到若干個源文件中,再由若干源文件組成一個C程序。這樣可以分別編寫、分別編譯,提高調試效率。一個源文件可以為多個C程序公用。第六頁,共八十三頁,編輯于2023年,星期五2023/5/2367-1概述(3)C程序的執(zhí)行從main函數(shù)開始,調用其它函數(shù)后流程回到main函數(shù),在main函數(shù)中結束整個程序的運行。main函數(shù)是系統(tǒng)定義的。第七頁,共八十三頁,編輯于2023年,星期五2023/5/2377-1概述(4)所有函數(shù)都是平行的,即在定義函數(shù)時是互相獨立的,一個函數(shù)并不從屬于另一函數(shù),即函數(shù)不能嵌套定義,但可以互相調用,甚至嵌套調用、遞歸調用(注:不能調用main函數(shù))。第八頁,共八十三頁,編輯于2023年,星期五2023/5/2387-1概述(5)從用戶使用的角度看,函數(shù)有兩種:①標準函數(shù),即庫函數(shù)。這是由系統(tǒng)提供的,用戶無須定義,也不必在程序中作類型說明,只需在程序前包含有該函數(shù)原型的頭文件即可在程序中直接調用。②用戶自己定義的函數(shù),以解決用戶的專門需要。第九頁,共八十三頁,編輯于2023年,星期五2023/5/2397-1概述(6)從函數(shù)的形式看,函數(shù)分兩類:①無參函數(shù)。在調用無參函數(shù)時,主調函數(shù)并不將數(shù)據(jù)傳送給被調用函數(shù),一般用來執(zhí)行指定的一組操作。無參函數(shù)可以帶回也可以不帶回函數(shù)值,但一般以不帶回函數(shù)值的居多。②有參函數(shù)。在調用函數(shù)時,在主調函數(shù)和被調用函數(shù)之間有參數(shù)傳遞,也就是說,主調函數(shù)可以將數(shù)據(jù)傳給被調用函數(shù)使用,被調用函數(shù)中的數(shù)據(jù)也可以帶回來供主調函數(shù)使用。第十頁,共八十三頁,編輯于2023年,星期五2023/5/23107-2函數(shù)定義的一般形式

7-2-1無參函數(shù)的定義無參函數(shù)定義形式:類型標識符函數(shù)名(){聲明部分語句部分}例如:print(){printf("welcome");}printstar(){printf("*******");}main(){printstar();print();printstar();}第十一頁,共八十三頁,編輯于2023年,星期五2023/5/23117-2函數(shù)定義的一般形式

7-2-2有參函數(shù)的定義有參函數(shù)定義形式:類型標識符函數(shù)名(類型名形式參數(shù)1,類型名形式參數(shù)2…){聲明部分語句部分}例如:

intmax(intx,inty)/*函數(shù)的首部*/{intz;/*函數(shù)體中的聲明部分*/

z=x>y?x:y;/*語句部分*/

return(z);/*語句部分*/}第十二頁,共八十三頁,編輯于2023年,星期五2023/5/23127-2函數(shù)定義的一般形式

7-2-3空函數(shù)的定義定義形式:類型標識符函數(shù)名(){}例如:fun(){}調用此函數(shù)時,什么也不做。在主調函數(shù)中寫上fun();表明這里要調用一個函數(shù),而現(xiàn)在這個函數(shù)還沒有完成,等以后擴充函數(shù)功能時補充上。第十三頁,共八十三頁,編輯于2023年,星期五2023/5/23137-3函數(shù)參數(shù)和函數(shù)的值

7-3-1形式參數(shù)和實際參數(shù)在調用函數(shù)時,大多數(shù)情況下,主調函數(shù)和被調用函數(shù)之間有數(shù)據(jù)傳遞關系。在定義函數(shù)時函數(shù)名后面括弧中的變量名稱為“形式參數(shù)”(簡稱“形參”),在調用函數(shù)時,函數(shù)名后面括弧中的表達式稱為“實際參數(shù)”(簡稱“實參”)。

第十四頁,共八十三頁,編輯于2023年,星期五2023/5/23147-3函數(shù)參數(shù)和函數(shù)的值

(1)在定義函數(shù)中指定的形參變量,在未出現(xiàn)函數(shù)調用時,它們并不占內存中的存儲單元。只有在函數(shù)被調用時函數(shù)的形參才被分配內存單元。在調用結束后,形參所占的內存單元也被釋放。第十五頁,共八十三頁,編輯于2023年,星期五2023/5/23157-3函數(shù)參數(shù)和函數(shù)的值

(2)形參只能是變量,而實參可以是常量、變量或表達式,在調用時將實參的值傳遞給形參(如果實參是數(shù)組名,則傳遞的是數(shù)組地址而不是變量的值,參見第8章)。(3)在被定義的函數(shù)中,必須指定形參的類型。第十六頁,共八十三頁,編輯于2023年,星期五2023/5/23167-3函數(shù)參數(shù)和函數(shù)的值

(4)實參與形參的個數(shù)應一樣、類型應一致。如果實參為整型而形參為實型,或者相反,則會發(fā)生“類型不匹配”的錯誤。但編譯程序一般不會給出錯誤信息,即使有時得不到確定結果,通常會繼續(xù)運行下去。字符型與整型可以互相通用。第十七頁,共八十三頁,編輯于2023年,星期五2023/5/23177-3函數(shù)參數(shù)和函數(shù)的值

(5)C語言規(guī)定,實參對形參的數(shù)據(jù)傳遞是單向傳遞,只由實參傳給形參,而不能由形參傳回來給實參。在內存中,實參單元與形參單元是不同的單元。第十八頁,共八十三頁,編輯于2023年,星期五2023/5/2318函數(shù)調用過程1.函數(shù)定義(編譯)時,形參不占用內存空間,所以形參只是一個“符號”,沒有值2.當函數(shù)被調用時,為形參分配內存空間,并把實參的值傳遞給形參,從此,實參與形參沒有任何聯(lián)系。3.當函數(shù)調用結束后,形參釋放內存空間,形參消失。4.形參只能是動態(tài)局部變量,實參只要是合法的表達式就行。第十九頁,共八十三頁,編輯于2023年,星期五2023/5/23197-3函數(shù)參數(shù)和函數(shù)的值

【例7-2】通過以下程序能否計算a與b中值的和,請分析。main(){inta=1,b=2,c=0;/*(1)開辟三個存儲單元a,b,c并分別存放1,2,0*/sum(a,b,c);/*(2)調用函數(shù)。a,b,c是實參,將它們的值1,2,0分別傳給形參*/printf("c=%d\n",c);}/*(6)輸出c中的值,因為是單向傳遞,z的改變不影響c的值*/sum(intx,inty,intz)/*(3)為形參x,y,z開辟單元,x,y,z分別從實參得到1,2,0*/{z=x+y;/*(4)執(zhí)行函數(shù)體*/}/*(5)結束調用,x,y,z被釋放*/運行結果是:c=0第二十頁,共八十三頁,編輯于2023年,星期五2023/5/23207-3函數(shù)參數(shù)和函數(shù)的值7-3-2函數(shù)的返回值通常,希望通過函數(shù)調用使主調函數(shù)能得到一個確定的值,這就是函數(shù)的返回值。說明:(1)函數(shù)的返回值是通過函數(shù)中的return語句獲得的。return語句的一般形式是:

return(表達式);或return表達式;或return;return語句中的表達式的值就是所求的函數(shù)值。如果return語句后面沒有表達式,則沒有確定的函數(shù)值。一個函數(shù)中可以有一個以上的return語句,但執(zhí)行到其中一個return語句,就結束該函數(shù)的調用。第二十一頁,共八十三頁,編輯于2023年,星期五2023/5/23217-3函數(shù)參數(shù)和函數(shù)的值(2)如果不需要從被調用函數(shù)帶回函數(shù)值,可以不要return語句,這時執(zhí)行到函數(shù)體中的最后一條語句后,自動退出調用函數(shù),而且?guī)Щ夭淮_定的返回值。(3)函數(shù)值的類型。既然函數(shù)可以有返回值,這個值當然應屬于某一個確定的類型,應當在定義函數(shù)時指定函數(shù)值的類型。第二十二頁,共八十三頁,編輯于2023年,星期五2023/5/23227-3函數(shù)參數(shù)和函數(shù)的值(4)在定義函數(shù)時,對函數(shù)值聲明的類型一般應該和return語句中的表達式類型一致。如果它們的類型不一致,則以函數(shù)值的類型為準。對數(shù)值型數(shù)據(jù),可以自動進行類型轉換,即函數(shù)類型決定返回值的類型。(5)為了明確表示“不帶回值”,可以用“void”定義“無類型”(或稱“空類型”)。例如:voidprintstar(){…}第二十三頁,共八十三頁,編輯于2023年,星期五2023/5/23237-3函數(shù)參數(shù)和函數(shù)的值

【例7-3】將例7-2改寫成如下形式后,重新分析之。

#include<stdio.h>main(){inta=1,b=2,c;/*(1)開辟三個存儲單元a,b,c,并分別給a,b賦1,2*/

c=sum(a,b);/*(2)調用函數(shù).a(chǎn),b是實參,將函數(shù)返回值賦給c*/

printf("c=%d\n",c);}/*(6)輸出c的值,因為通過函數(shù)返回值給c,c的值改變*/

intsum(intx,inty)

/*(3)形參x,y分別從實參得到1,2,函數(shù)值的類型為整型*/

{intz;/*(4)在函數(shù)內使用的變量*/

z=x+y;returnz;/*(5)結束調用,x,y,z被釋放,將z的值作為函數(shù)返回值*/

}運行結果是:c=3

第二十四頁,共八十三頁,編輯于2023年,星期五2023/5/23247-4函數(shù)的調用

7-4-1函數(shù)調用的形式函數(shù)調用的一般形式:

函數(shù)名(實參表列);如果是調用無參函數(shù),則實參表列可以沒有,但括弧不能省略。如果實參表列包含多個參數(shù),則各參數(shù)間用逗號隔開。實參與形參的個數(shù)應相等,類型應一致。實參與形參按順序對應,一一傳遞數(shù)據(jù)。第二十五頁,共八十三頁,編輯于2023年,星期五2023/5/23257-4函數(shù)的調用

【例7-4】寫出運行結果main(){intk=2,t;t=f(k,++k);printf("%d",t);}intf(inta,intb){intc;if(a>b)c=1;if(a<b)c=-1;if(a==b)c=0;returnc;}在TurboC系統(tǒng)上運行結果為:0第二十六頁,共八十三頁,編輯于2023年,星期五2023/5/23267-4函數(shù)的調用

7-4-2函數(shù)調用的方式1.函數(shù)語句把函數(shù)調用作為一個語句。如:printstar();不要求函數(shù)帶回值,只要求函數(shù)完成一定的操作。2.函數(shù)表達式函數(shù)出現(xiàn)在一個表達式中,這種表達式稱為函數(shù)表達式,這時要求函數(shù)帶回一個確定以參加表達式的運算。例如:c=2*max(a,b);3.函數(shù)參數(shù)把函數(shù)調用得到的值作為一個函數(shù)的實參例如:m=max(a,max(b,c));第二十七頁,共八十三頁,編輯于2023年,星期五2023/5/23277-4函數(shù)的調用

7-4-3對被調用函數(shù)的聲明和函數(shù)原型(1)首先被調用的函數(shù)必須是已經(jīng)存在的函數(shù)(是庫函數(shù)或用戶自己定義的函數(shù))。(2)如果使用庫函數(shù),一般還應該在本文件開頭用#include命令將調用有關庫函數(shù)時所需用到的信息包含到本文件中來。例如#include"stdio.h"或#include<stdio.h>

第二十八頁,共八十三頁,編輯于2023年,星期五2023/5/23287-4函數(shù)的調用

7-4-3對被調用函數(shù)的聲明和函數(shù)原型

(3)如果使用用戶自己定義的函數(shù),而且該函數(shù)與調用它的函數(shù)(即主調函數(shù))在同一個文件中,一般還應該在文件的開頭或在主調函數(shù)中對被調函數(shù)的類型進行聲明,這種類型聲明的一般形式為:返回值的類型名函數(shù)名();第二十九頁,共八十三頁,編輯于2023年,星期五2023/5/23297-4函數(shù)的調用

【例7-5】計算a與b的值的平方根之和。#include<stdio.h>#include<math.h>/*在函數(shù)中使用數(shù)學函數(shù)sqrt,因此要寫此行*/main(){floatadd(float,float);

/*對被調函數(shù)的聲明*/

floata,b,c;scanf("%f%f",&a,&b);c=add(a,b);printf("sumis%f\n",c);}floatadd(floatx,floaty)/*定義add函數(shù),返回值類型是float型*/{doublez;z=sqrt(x)+sqrt(y);/*相當于z=sqrt((double)x)+sqrt((double)y)*/

return(z);/*相當于return(float)z;,因為返回值類型為float型*/

}運行輸入1636<回車>輸出結果為:

sumis10.000000第三十頁,共八十三頁,編輯于2023年,星期五2023/5/23307-4函數(shù)的調用

C語言規(guī)定,在以下幾種情況下可以不用在調用函數(shù)前對被調用函數(shù)作原型聲明:

(1)如果函數(shù)的值(函數(shù)的返回值)是整型或字符型,可以不必進行聲明,系統(tǒng)對它們自動按整型聲明。

第三十一頁,共八十三頁,編輯于2023年,星期五2023/5/23317-4函數(shù)的調用

(2)如果被調用函數(shù)的定義出現(xiàn)在主調函數(shù)之前,可以不必加以聲明,因為編譯系統(tǒng)已經(jīng)先知道了已定義的函數(shù),會自動處理的。

(3)如果已在所有函數(shù)定義之前,在文件的開頭,在函數(shù)的外部已聲明了函數(shù)原型,則在各個主調函數(shù)中不必對所調用的函數(shù)再作原型聲明。第三十二頁,共八十三頁,編輯于2023年,星期五2023/5/23327-4函數(shù)的調用

(4)ANSIC標準在對函數(shù)進行類型聲明時,除了規(guī)定要聲明函數(shù)的類型外,還要求聲明參數(shù)個數(shù)與參數(shù)類型,這是為了在編譯時檢查函數(shù)的調用是否合法(如實參的個數(shù)和類型與形參是否一致)。這樣的聲明稱為用函數(shù)原型作聲明。函數(shù)原型的一般形式是:函數(shù)類型函數(shù)名(參數(shù)類型l參數(shù)名1,參數(shù)類型2參數(shù)名2…);這種形式就是把定義函數(shù)時的函數(shù)首部(即第一行)搬過來加一個分號即可。第三十三頁,共八十三頁,編輯于2023年,星期五2023/5/23337-4函數(shù)的調用

7-4-4程序舉例【例7-6】閱讀下面程序,判斷程序能否交換主函數(shù)中a和b的值。

main(){inta=1,b=2;swap(a,b);/*a、b是實參*/printf("實參:a=%d,b=%d\n",a,b);/*輸出實參a、b的值*/}swap(inta,intb)/*a,b是形參,開辟與實參a、b不同的存儲單元*/{intc;c=a;a=b;b=c;/*交換形參a、b中的值*/printf("形參:a=%d,b=%d\n",a,b);/*輸出形參a、b的值*/}/*調用完畢,釋放a、b、c所占存儲單元*/運行結果是:形參:a=2,b=1

實參:a=1,b=2第三十四頁,共八十三頁,編輯于2023年,星期五2023/5/23347-4函數(shù)的調用【例7-7】由鍵盤輸人三個整數(shù)分別給變量a、b、c,輸出其中絕對值最大的數(shù)。#include<stdio.h>#include<math.h>main(){inta,b,c,max;scanf("%d,%d,%d",&a,&b,&c);max=find(a,b,c);/*編寫主調函數(shù)時,可以不必具體考慮如何編寫被調函數(shù),只要知道返回值是三個數(shù)中絕對值最大者即可*/printf("max=%d\n",max);}intfind(intx,inty,intz){intmax;max=x;if(abs(max)<abs(y))max=y;if(abs(max)<abs(z))max=z;returnmax;}運行結果:

123,345,91<回車>max=345第三十五頁,共八十三頁,編輯于2023年,星期五2023/5/23357-4函數(shù)的調用【例7-8】求100~200之間的全部素數(shù)之和。#include<math.h>main(){intm,s=0;for(m=101;m<200;m=m+2)if(prime(m))s+=m;printf("s=%d\n",s);}intprime(intm){intk,j;k=sqrt(m);for(j=2;j<=k;j++)if(m%j==0)return0;return1;}運行結果如下:

s=3167第三十六頁,共八十三頁,編輯于2023年,星期五2023/5/23367-5函數(shù)的嵌套調用C語言程序不能嵌套定義函數(shù),但可以嵌套調用函數(shù),也就是說,在調用一個函數(shù)的過程中,又可以調用另一個函數(shù)main函數(shù)a函數(shù)b函數(shù)調用a函數(shù)調用b函數(shù)結束123456789第三十七頁,共八十三頁,編輯于2023年,星期五2023/5/23377-5函數(shù)的嵌套調用【例7-9】求1!+2!+3!+4!+…+20!main(){floatsum(int);/*函數(shù)sum的原型聲明*/floatadd;add=sum(20);/*主函數(shù)調用sum函數(shù),求20以內的自然數(shù)的階乘和*/printf("add=%e",add);/*由于20以內的自然數(shù)的階乘和超過int型和long型能表示的數(shù)的范圍,所以用e格式輸出結果*/}floatsum(intn)/*求n以內的自然數(shù)的階乘和*/{floatfac(int);/*函數(shù)fac的原型聲明*/intk;floats=0;for(k=1;k<=n;k++)s+=fac(k);/*調用fac求k!,并累加到s中*/returns;/*返回n以內的自然數(shù)的階乘和*/}floatfac(intk)/*求k的階乘值*/{floatt=1;intn;for(n=1;n<=k;n++)t*=n;returnt;/*返回k的階乘值*/}運行結果為:

s=2.56133e+18第三十八頁,共八十三頁,編輯于2023年,星期五2023/5/23387-6函數(shù)的遞歸調用在C語言程序中,有時可以看到一個函數(shù)直接或間接地調用自身的現(xiàn)象,這種現(xiàn)象就是函數(shù)的遞歸調用。遞歸調用有兩種方式:直接遞歸調用和間接遞歸調用。f函數(shù)調用f函數(shù)圖7-2f1函數(shù)f2函數(shù)調用f2函數(shù)調用f1函數(shù)圖7-3第三十九頁,共八十三頁,編輯于2023年,星期五2023/5/23397-6函數(shù)的遞歸調用【例7-10】用遞歸調用的方法求n!。

1當n=0或1時n!=n*(n-1)當n>1時

intfac(intn){intc;if(n==0||n==1)c=1;/*n的值為0或1時,n!為1*/elsec=n*fac(n-1);/*n>l時,調用本函數(shù)計算n!*/returnc;/*c中存放的是n!,返回值也是n!*/}main(){intn;scanf("%d",&n);if(n<0)printf("Dataerror!\n");elseprintf("%d!=%d\n",n,fac(n));}

運行結果如下:

4<回車>4!=24第四十頁,共八十三頁,編輯于2023年,星期五2023/5/23407-6函數(shù)的遞歸調用遞歸不是“循環(huán)定義”,任何遞歸定義必須滿足如下條件:(1)被定義項在定義中的應用(即作為定義項的出現(xiàn))具有更小的“尺度”,即需要求解的問題可以分解為一個相對簡單的子問題。(2)被定義項在最小“尺度”上的定義不是遞歸的,即最終有一個子問題不是遞歸,必須有確定的值。第四十一頁,共八十三頁,編輯于2023年,星期五2023/5/23417-6函數(shù)的遞歸調用【例7-11】編程求Fibonacci數(shù)列的第n項。Fibonacci數(shù)列定義如下:

1當n=1時F(n)=1當n=2時

F(n-1)+F(n-2)當n>2時longfibo(int);main(){longf;intn;scanf("%d",&n);f=fibo(n);printf("%ld\n",f);}longfibo(intn){longf;if(n==1||n==2)f=1L;elsef=fibo(n-1)+fibo(n-2);returnf;}運行時結果:8<回車>21第四十二頁,共八十三頁,編輯于2023年,星期五2023/5/23427-7局部變量和全局變量

-7-1局部變量在一個函數(shù)或復合語句內部定義的變量是內部變量,它只在本函數(shù)或復合語句范圍內有效,也就是說只能在本函數(shù)或復合語句內才能使用它們,這樣的變量稱為“局部變量”。第四十三頁,共八十三頁,編輯于2023年,星期五2023/5/23437-7局部變量和全局變量

floatf1(inta)/*函數(shù)f1*/{intb,c;……}/*在此函數(shù)內a,b,c有效,它們不是主函數(shù)中的a,b,c*/main(){inta,b;{intc=0;c=a+b;/*c只在復合語句內有效*/}……}/*在主函數(shù)內,a,b一直有效*/第四十四頁,共八十三頁,編輯于2023年,星期五2023/5/23447-7局部變量和全局變量

【例7-12】寫出下面程序的運行結果。

main(){intk,a=0;for(k=1;k<=2;k++){inta=1;/*在復合語句內開辟新的a,故上面的a不起作用*/a++;printf("k=%d,a=%d\n",k,a);}/*釋放復合語句內開辟的a,不能再使用它*/printf("k=%d,a=%d\n",k,a);/*a是主函數(shù)第一條語句中的a*/}運行結果是:

k=l,a=2k=2,a=2k=3,a=0第四十五頁,共八十三頁,編輯于2023年,星期五2023/5/23457-7局部變量和全局變量

7-7-2全局變量在函數(shù)之外定義的變量稱為外部變量,外部變量是全局變量。全局變量可以為本文件中其它函數(shù)所共用,它的有效范圍為:從定義變量的位置開始到本源文件結束第四十六頁,共八十三頁,編輯于2023年,星期五2023/5/23467-7局部變量和全局變量

inta=l,b=2;/*a,b為全局變量,以下三個函數(shù)都可以使用*/floatfl(inta)/*定義函數(shù)fl*/{intb,c;……}/*a,b,c只在本函數(shù)中使用*/intc=0,d=2;/*c,d為全局變量,以下兩個函數(shù)可以使用它們*/f2(intx,inty)/*定義函數(shù)f2*/{inti,j;……}/*x,y,i,j只在本函數(shù)內有效*/main(){intm,n;/*m,n只在主函數(shù)內有效*/……}第四十七頁,共八十三頁,編輯于2023年,星期五2023/5/23477-7局部變量和全局變量

7-7-2全局變量(1)設全局變量的作用是:增加函數(shù)間數(shù)據(jù)聯(lián)系的渠道。由于同一文件中的所有函數(shù)都能引用全局變量的值,因此,如果在一個函數(shù)中改變了全局變量的值,就能影響到其它函數(shù),相當于各個函數(shù)間有直接的傳遞通道。由于函數(shù)的調用只能帶回一個返回值,因此有時可以利用全局變量增加與函數(shù)聯(lián)系的渠道,從函數(shù)得到一個以上的返回值。第四十八頁,共八十三頁,編輯于2023年,星期五2023/5/23487-7局部變量和全局變量7-7-2全局變量

(2)建議不在必要時不要使用全局變量,因為:①全局變量在程序的全部執(zhí)行過程中都占用存儲單元,而不是僅在需要時才開辟單元;②它使函數(shù)的通用性降低了,因為函數(shù)在執(zhí)行時要依賴于其所在的外部變量。如果將一個函數(shù)移到另一個文件中,還要將有關的外部變量及其值一起移過去,但若該外部變量與其它文件的變量同名時,就會出現(xiàn)問題,降低了程序的可靠性和通用性;③使用全局變量過多,會降低程序的清晰性,人們往往難以清楚地判斷出每個瞬時各個外部變量的值。在各個函數(shù)執(zhí)行時都可能改變外部變量的值,程序容易出錯,因此要限制使用全局變量。第四十九頁,共八十三頁,編輯于2023年,星期五2023/5/23497-7局部變量和全局變量7-7-2全局變量

(3)如果外部變量在文件開頭定義,則在整個文件范圍內都可以使用該外部變量,如果不在文件開頭定義,按上面規(guī)定作用范圍只限于定義點到文件終點。如果在定義點之前的函數(shù)想引用該外部變量,則應該在該函數(shù)中用關鍵字extern作“外部變量聲明”。這聲明表示這些變量是在該函數(shù)后面定義的外部變量。在函數(shù)內部,從extern聲明之處起,可以使用它們。第五十頁,共八十三頁,編輯于2023年,星期五2023/5/23507-7局部變量和全局變量【例7-13】程序示例。intmax(intx,inty)/*定義max函數(shù)*/{intz;z=x>y?x:y;return(z);}main(){externinta,b;/*外部變量聲明,不重新開辟內存空間*/printf("%d",max(a,b));}inta=20,b=7;運行結果:

20第五十一頁,共八十三頁,編輯于2023年,星期五2023/5/23517-7局部變量和全局變量7-7-2全局變量(4)如果在同一個源文件中,外部變量與局部變量同名,則在局部變量的作用范圍內,外部變量不起作用。第五十二頁,共八十三頁,編輯于2023年,星期五2023/5/23527-7局部變量和全局變量【例7-14】inta=1;/*定義全局變量a*/f(){inta=2;printf("f:a=%d\n",a);/*f中的局部變量a起作用*/}g(){printf("g:a=%d\n",a);/*全局變量a起作用*/}main(){inta=3;printf("main:a=%d\n",a);/*main中的局部變量a起作用*/f();g();}運行時輸出:main:a=3f:a=2g:a=1第五十三頁,共八十三頁,編輯于2023年,星期五2023/5/23537-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-1變量的存儲類別從變量的作用域(即從空間)角度來分,可以分為全局變量和局部變量。從變量值存在的時間(即生存期)來分,可以分為靜態(tài)存儲變量和動態(tài)存儲變量。所謂靜態(tài)存儲方式是指在程序運行期間分配固定的存儲空間的方式,而動態(tài)存儲方式則是在程序運行期間根據(jù)需要進行動態(tài)的分配存儲空間的方式。第五十四頁,共八十三頁,編輯于2023年,星期五2023/5/23547-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-1變量的存儲類別內存中的供用戶使用的存儲空間可以分為三部分:(1)程序區(qū)(2)靜態(tài)存儲區(qū)(3)動態(tài)存儲區(qū)數(shù)據(jù)分別存放在靜態(tài)存儲區(qū)和動態(tài)存儲區(qū)中。全局變量存放在靜態(tài)存儲區(qū)中,在程序開始執(zhí)行時給全局變量分配存儲區(qū),程序執(zhí)行完畢就釋放。在程序執(zhí)行過程中它們占據(jù)固定的存儲單元,而不是動態(tài)地分配和釋放的。第五十五頁,共八十三頁,編輯于2023年,星期五2023/5/23557-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-1變量的存儲類別在動態(tài)存儲區(qū)中存放以下數(shù)據(jù):①函數(shù)形參變量,在調用函數(shù)時給形參變量分配存儲空間;②局部變量;③函數(shù)調用時的現(xiàn)場保護和返回地址等。對以上這些數(shù)據(jù),在函數(shù)調用開始時分配動態(tài)存儲空間,函數(shù)結束時釋放這些空間。第五十六頁,共八十三頁,編輯于2023年,星期五2023/5/23567-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-1變量的存儲類別在C語言中每一個變量和函數(shù)有兩個屬性:數(shù)據(jù)類型和數(shù)據(jù)的存儲類別。存儲方法分為兩大類:靜態(tài)存儲類和動態(tài)存儲類。具體包含四種:自動的(auto),靜態(tài)的(static),寄存器的(register),外部的(extern)。第五十七頁,共八十三頁,編輯于2023年,星期五2023/5/23577-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式(1)函數(shù)中的局部變量,如不做專門的聲明,都是動態(tài)分配存儲空間的,存儲在動態(tài)存儲區(qū)中,對它們分配和釋放存儲空間的工作是由編譯系統(tǒng)自動處理的,因此這類局部變量稱為局部動態(tài)變量或稱自動變量。自動變量用關鍵字auto作存儲類型的聲明。“auto”也可以省略,auto不寫則隱含確定為“自動存儲類別”,它屬于動態(tài)存儲類別。第五十八頁,共八十三頁,編輯于2023年,星期五2023/5/23587-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式(2)有時希望函數(shù)中的局部變量的值在函數(shù)調用結束后不消失而保留原值,即其占用的存儲單元不釋放,在下一次調用該函數(shù)時,該變量已有上一次函數(shù)調用結束時保留下來的值。為此,應該指定該局部變量為“局部靜態(tài)變量”,用static加以聲明。第五十九頁,共八十三頁,編輯于2023年,星期五2023/5/23597-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式【例7-15】寫出下面程序的運行結果。voidf(intc){inta=0;/*每次調用時都先賦0,不保留上一次的值*/staticintb=0;/*第一次調用時初值為0,下次調用時保留上一次的值*/a++;b++;printf("%d:a=%d,b=%d\n",c,a,b);}main(){intk;for(k=1;k<=2;k++)f(k);/*調用兩次函數(shù)*/}運行結果是:

1:a=1,b=12:a=1,b=2第六十頁,共八十三頁,編輯于2023年,星期五2023/5/23607-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式對局部靜態(tài)變量的說明:①局部靜態(tài)變量屬于靜態(tài)存儲類別,在靜態(tài)存儲區(qū)內分配存儲單元。在程序整個運行期間都不釋放。而自動變量(即局部動態(tài)變量)屬于動態(tài)存儲類別,占動態(tài)存儲區(qū)空間而不占固定空間,函數(shù)調用結束后即釋放。第六十一頁,共八十三頁,編輯于2023年,星期五2023/5/23617-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式②局部靜態(tài)變量是在編譯時賦初值的,即只賦初值一次,在程序運行時它已有初值,以后每次調用函數(shù)時不再重新賦初值而只是保留上次函數(shù)調用結束時的值。而對自動變量賦初值,不是在編譯時進行的,而在函數(shù)調用時進行,每調用一次函數(shù)重新賦一次初值。第六十二頁,共八十三頁,編輯于2023年,星期五2023/5/23627-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式③如在定義局部變量時不賦初值的話,則對靜態(tài)變量來說,編譯時自動賦初值0(對數(shù)值型變量)或空字符(對字符變量),而對自動變量來說,它的值是一個不確定的值。這是由于每次函數(shù)調用結束后存儲單元已釋放,下次調用時又重新分配另一存儲單元,因此所分配的單元中的值是不確定的。以上結論對數(shù)組的初始化也成立。第六十三頁,共八十三頁,編輯于2023年,星期五2023/5/23637-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式【例7-16】寫出以下程序的運行結果。main(){intk,a[5];for(k=0;k<5;k++)printf("%d",a[k]);/*a數(shù)組沒有賦值,輸出一行隨機數(shù)*/printf("\n");printf("Firsttime:\n");fun();/*第一次調用時,為數(shù)組a的全部元素自動賦0*/printf("Secondtime:\n");fun();/*第二次調用時,保留數(shù)組a的原值*/}fun()/*由于定義為靜態(tài)變量,兩次調用的結果不同*/{inti;staticinta[5];for(i=0;i<5;i++)printf("%d",a[i]);printf("\n");a[0]++;/*改變a[0]的值*/}運行結果是:**************

Firsttime:00000Secondtime:10000(其中**************代表隨機數(shù))

第六十四頁,共八十三頁,編輯于2023年,星期五2023/5/23647-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式④雖然局部靜態(tài)變量在函數(shù)調用結束后仍然占存儲單元,但由于該變量是局部變量,其它函數(shù)不能引用它。第六十五頁,共八十三頁,編輯于2023年,星期五2023/5/23657-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式應該看到:用靜態(tài)存儲要多占內存(長期占用不釋放,而不能像動態(tài)存儲那樣一個存儲單元可供多個變量使用,節(jié)約內存),而且降低了程序的可讀性,當調用次數(shù)多時往往弄不清局部靜態(tài)變量的當前值是什么。因此,如不必要,不要多用局部靜態(tài)變量。第六十六頁,共八十三頁,編輯于2023年,星期五2023/5/23667-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式(3)為了減少從內存中存取變量值的時間,以提高執(zhí)行效率,C語言允許將局部變量的值放在運算器中的寄存器中,需要時直接從寄存器取出。這種變量叫“寄存器變量”,用關鍵字register作聲明。第六十七頁,共八十三頁,編輯于2023年,星期五2023/5/23677-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式【例7-17】輸出1到5的階乘值。

intfac(intn){registerinti,f=1;

/*i和f使用頻繁,因此定義為寄存器變量*/

for(i=1;i<=n;i++)f=f*i;return(f);}main(){inti;for(i=1;i<=5;i++)printf("%d!=%d\n",i,fac(i));}運行結果為:1!=12!=23!=64!=245!=120第六十八頁,共八十三頁,編輯于2023年,星期五2023/5/23687-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式①只有局部自動變量和形式參數(shù)可以作為寄存器變量,其它(如全局變量)不行。在調用一個函數(shù)時占用一些寄存器以存放寄存器變量的值,函數(shù)調用結束釋放寄存器。此后,在調用另一個函數(shù)時又可以利用它來存放該函數(shù)的寄存器變量。第六十九頁,共八十三頁,編輯于2023年,星期五2023/5/23697-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式②一個計算機系統(tǒng)中的寄存器數(shù)目是有限的,不能定義任意多個寄存器變量。不同的系統(tǒng)允許使用的寄存器個數(shù)不同。如果沒有足夠的寄存器來存放指定的變量,將自動按自動變量來處理。寄存器變量的聲明應盡量靠近使用它的地方,用完之后盡快釋放。第七十頁,共八十三頁,編輯于2023年,星期五2023/5/23707-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-2局部變量的存儲方式③局部靜態(tài)變量不能定義為寄存器變量,不能寫成:registerstaticinta,b,c;不能把變量a,b,c既放在靜態(tài)存儲區(qū)中,又放在寄存器中,二者只能居其一。④不能對寄存器變量進行求地址運算,因為寄存器變量的值不是存放在內存中。第七十一頁,共八十三頁,編輯于2023年,星期五2023/5/23717-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-3全局變量的存儲方式全局變量是在函數(shù)的外部定義的,編譯時分配在靜態(tài)存儲區(qū)。全局變量可以為程序中各個函數(shù)所引用。第七十二頁,共八十三頁,編輯于2023年,星期五2023/5/23727-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-3全局變量的存儲方式(1)允許其它文件中的函數(shù)引用。如果在一個文件中要引用在另一文件中定義的全局變量,應該在需要引用它的文件中用extern作聲明。

第七十三頁,共八十三頁,編輯于2023年,星期五2023/5/23737-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-3全局變量的存儲方式(2)只被本文件中的函數(shù)引用。有時在程序設計中希望某些全局變量只限于被本文件引用而不能被其它文件引用,這時可以在定義外部變量時前面加一個static聲明。加上static聲明、只能用于本文件的外部變量(全局變量)稱為靜態(tài)外部變量。

第七十四頁,共八十三頁,編輯于2023年,星期五2023/5/23747-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-4存儲類別小結1.共有四種存儲類別:

static(聲明靜態(tài)內部變量或外部靜態(tài)變量)

auto(聲明自動局部變量)

register(聲明寄存器變量)extern(聲明變量是已定義的外部變量)第七十五頁,共八十三頁,編輯于2023年,星期五2023/5/23757-8動態(tài)存儲變量與靜態(tài)存儲變量7-8-4存儲類別小結

2.從作用域分,有全局變量和局部變量。它們可采取的存儲類別為:局部變量:自動變量,即動態(tài)局部變量(離開函數(shù),值就消失);靜態(tài)局部變量(離開函數(shù),值仍保留);寄存器變量(離開函數(shù),值就消失);形式參數(shù)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論