




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第5章函數
2012年6月21日星期四
2012-6-21
2012-6-212
結構化程序設計方法,從程序實現的角度看就是
模塊化程序設計,就是將程序模塊化,即在程序
設計中通常將一個大的程序按功能進行分割成一
些模塊,使每個模塊都成為功能單一、結構清晰、
接口簡單、容易理解的小程序。在C語言中是通
過函數來實現模塊化程序設計的,即將那些較小
的功能單一的程序模塊稱之為函數,通過對函數
的調用實現特定的功能。所以較大的C語言應用
程序,往往是由多個函數組成的,每個函數分別
對應各自的功能模塊,通過函數的定義把實現的
細節封閉起來,通過函數調用組合各種功能。
2012-6-213
c語言提供以下一些功能來支持模塊化軟件開發:
(1)函數式的程序結構。程序整體由一個或多個
函數組成。
(2)允許通過使用不同存儲類別的變量,控制模
塊內部及外部的信息交換。
(3)具有編譯預處理功能,為程序的調試、移植
提供了方便。
2012-6-214
5.1函數概述
用C語言設計程序來求解任何一個問題時,主要任務
就是編寫函數。
進行C程序設計時一般采用自頂向下、逐步細化的
方法設計程序結構,即先集中考慮main函數中的算法。
當main函數中需要使用某一功能時,就先寫上一個調用
具有該功能的函數的表達式。這時只需知道函數具有什
么功能,如何與程序通信(輸入什么,輸出什么),函
數的具體實現先不去處理。設計完main()函數的算法并
檢驗無誤后,再開始考慮它所調用函數的具體實現。在
這些被調用的函數中,若在庫函數中可以找到,那就直
接使用,否則就動手設計這些函數。
2012-6-215
【例5.1】分別求兩個長方形的面積。
分析:采用模塊化程序設計的思想,將計算長方形面積的
代碼段提煉出來,寫成函數,當需要這段代碼時,就調
用該函數。
include<stdio.h>
intmain()/*先設計main函數*/
(
inta,b,c,d,s1,s2;
printf("Pleaseinputthewidthandtheheight(two
rectangular):");
nn
scanf(%d%d%d%d,&a5&b,&c,&d);/*調用輸入庫函數*
s1=area(a,b);/*調用自定義函數area*/
s2=area(c,d);/*再次調用自定義函數area*/
printf("theareaofthefirstrectangularis%d\nH,s1);
printf("theareaofthesecondrectangularis%d",s2);
return0;"
-2012-6-216
intarea(intx,inty)/*再設計自定義函數area7
(
intz;
z=x*y;
returnz;
)
由此可以看出,在c程序設計中使用函數可以
減少重復編寫程序的工作量,使程序便于調試
和閱讀。
2012-6-217
5.2函數的分類
C語言中可從不同的角度給函數分類。
1.從函數定義的角度
(1)庫函數
由C系統提供,用戶無須定義,也不必在程序中
作類型說明,只需在程序前包含有該函數原型的
頭文件即可在程序中直接調用。在前面章節中用
至U的printf、scanf>getchar>putchar等函數均屬
庫函數。
C語言提供了豐富的庫函數,字符類型函數、轉換
函數、字符串函數、數學函數、輸入輸出函數等
等,詳見附錄IV。
2012-6-218
(2)用戶自定義函數
系統提供的庫函數不能完全滿足用戶的特
殊需求時,由用戶按需要自己設計的函數。
用戶可按C語言的函數規則定義其函數名稱、
使用的參數、完成的功能和運行的結果。
如例5.1中的area函數是用戶自定義函數。
2012-6-219
2.從主調函數和被調函數間數據傳送的角度
(1)無參函數
函數定義、函數說明及函數調用中均不帶
參數。主調函數和被調函數之間不進行參
數傳送。此類函數通常用來完成一組指定
的功能,可以返回或不返回函數值。
(2)有參函數(帶參函數)
在函數定義及函數說明時都有參數,稱為
形式參數(簡稱為形參)。在函數調用時也
必須給出參數,稱為實際參數(簡稱為實
參)。進行函數調用時,主調函數將把實
參的值傳送給形參,供被調函數使用。
2012-6-2110
5.3函數的定義和調用
?5.3.1函數的定義
函數的定義格式為:
類型標識符函數名([形式參數列表])
(
類型聲明部分
執行語句部分
}
2012-6-2111
說明:
(1)函數名是由用戶定義的標識符,是唯一
標識一個函數的名字,它的命名規則同變
量的命名規則完全一樣。同一個程序中不
同的函數名字不能相同。
(2)類型標識符說明了函數的類型,即函數
返回值的類型。
(3)若形式參數列表為空,則該函數是無參
函數,此時函數名后面跟一對空圓括號。
2012-6-2112
(4)若有形式參數列表,則該函數是有參函
數。形參表用于調用函數和被調用函數之
間進行數據傳遞,形參表中的參數可以是
各種類型的變量,各參數之間用逗號間隔。
形參是變量,在形參表中應給出形參的類
型說明。
(5)由左、右花括號括起來的部分稱為函數
體,由類型聲明部分和執行語句部分組成。
類型聲明部分用于對函數內所使用的變量
的類型進行說明;執行語句部分由C語言的
基本語句組成,它是函數功能的核心部分。
聲明語句須放在執行語句之前。
2012-6-2113
(6)允許程序設計中使用空函數,該函數什
么也不做,沒有任何實際作用,先占一個
位置,在程序需要擴充功能時,再用一個
編好的函數取代它。
空函數的形式為:
void函數名()
()
2012-6-2114
【例5.2]定義無參函數。
include<stdio.h>
voidprint()
(
printfCHello!");
)
intmain()
(
print();/*調用函數print*/
return0;
)
運行結果如下:
Hello!
2012-6-2115
【例5.3]定義有參函數。
include<stdio.h>
intmain()
(
intx,y,z;
printf(Tleaseinputtwointeger:");
HH
scanf(%d%d,&xJ&y);
z=max(x,y);/*調用函數max7
printf(Hthemaxis%d.",z);
return0;
)
2012-6-2116
intmax(intm,intn)
/*定義函數max,求兩個數的最大值*/
(
ints;/*函數體的類型聲明部分*/
if(m>n)/*函數體執行語句部分的開始7
s=m;
else
s=n;
returns;/*函數體執行語句部分的結束*/
)
2012-6-2117
由上述兩個例子可以看出,在C程序中,
一個函數的定義可以放在任意位置,既可
放在主函數main之前,也可放在main之后。
在C語言中,所有的函數定義,包括主函
數main在內,都是平行的。也就是說,在
一個函數的函數體內,不能再定義另一個
函數,即函數不能嵌套定義。
2012-6-2118
5.3.2函數的調用
1.函數的一般調用形式
函數名(實際參數列表)
說明:
若是調用無參函數,則“實際參數列表”可
以沒有,但圓括號不能省略,如例5.2。若
“實際參數列表”包含多個實參,則各參
數間用逗號隔開,如例5.3。
2012-6-2119
2.函數的調用方式
按函數在程序中出現的位置來分,有以下三種函數調用方式。
(1)函數語句
把函數調用作為一個語句,如例5.2中“print。;”。
(2)函數表達式
函數出現在一個表達式中,這種表達式稱為函數表達式。
例如:z=max(x,y);
或z=2*max(x,y);
函數max是表達式的一部分,它的值乘以2再賦給z。
(3)函數參數
函數調用作為一個函數的實參。
例如:p=max(max(x,y),z);
這里,max(x,y)是一次函藪施用,它的值作為max另一次調用
的實參。p的值就是x,y,z三者的最大值。
又如:printf("%d",max(x,y));
這里,函羲調甫max(x,y)作Rprintf函數的一個參數。
2012-6-2120
3.被調用函數的使用說明
在程序中調用另一個函數時,要滿足以下三個條件。
(1)被調用函數可以是已經存在的用戶自定義函數或者
是系統庫函數。
(2)如果調用庫函數,應該在本程序開頭使用箱的1加6命
令將調用有關庫函數時所需用到的信息“包含”到本程
序中。
例如:
include<stdio.h>/*輸入輸出庫函數*/
include<math.h>/*數學庫函數*/
2012-6-2121
(3)如果調用用戶自定義的函數,且該函數與對該
函數的調用函數在同一個源文件中,特別是函數中
調用函數,則在主調函數中必須對被調用函數作類
型聲明。對被調用函數進行類型聲明就是告訴系統,
在本函數中將要用到的函數是什么類型,即函數的
返回值是什么類型,以便按聲明的類型對函數值作
相應的處理。
函數聲明的一般格式為:
類型標識符函數名(類型標識符形參名,類型標識
符形參名,…);
2012-6-2122
說明:
①對被調用函數聲明時,可以省略形參名。函數聲明語句后
面的分號不能省略。
②被調用函數的返回值是整型或字符型時,可以不對被調用
函數進行聲明,而直接調用。這時系統將自動對被調用函
數返回值按整型處理。
如例5.1和例5.3中的被調函數area和被調函數max的返回值
均為整型,所以在主調函數main函數中均未對被調函數作
類型聲明。
③如果被調用函數的定義出現在主調函數之前,可以不必對
被調用函數加以聲明。
如例5.2中被調函數print在主調函數main之前定義,所以在
主調函數main中不需要對被調函數print作類型聲明。
④如果在程序的開頭(在所有函數之前),已對本程序中所
調用的函數進行了聲明,則在各主調函數中不必對其所調
用的函數再作聲明。
2012-6-2123
【例5.4】計算n!。
include<stdio.h>
intmain()
longfac(int);/*對被調函數fac作類型聲明,省
略了參數名*/
intn;
longlayer;
print^Tleaseinputn:H);
scanf(”%cT,&n);
layer=fac(n);
printf(,,n=%d,%d!=%ld,,,n,n,layer);
return0;
}________________________________________
2012-6-2124
longfac(intx)
此例是在主調函數main中對被調函數
longy;fac作類型聲明,聲明語句double
fac(int)也可以放在程序的開頭,即:
inti;
#include<stdio.h>
y=1;doublefac(int);/*對被調函數fac
for(i=1;i<=x;i++)作類型聲明*/
intmain()
y=y*i;
returny;
)
)doublefac(intx)/*定義函數fac*/
)
2012-6-2125
關于函數調用還需要說明的是,在C程序中,
main函數是主函數,它可以調用其它函數,而不
允許被其它函數調用。因此,C程序的執行總是
從main函數開始,完成對其它函數的調用后再返
回到main函數,最后由main函數結束整個程序。
一個C源程序必須有,也只能有一個主函數main。
函數的使用和變量一樣,一般要求先定義后使用。
2012-6-2126
5.4函數的返回值
函數的返回值是指函數被調用之后,執行函數體
中的程序段所取得的并返回給主調函數的值。函
數調用的目的通常是為了得到一個計算結果即函
數值。在C程序中,利用返回語句return將計算結
果返回給主調函數,同時,也使程序的執行流程
轉到主調函數的下一條語句去執行。
返回語句的格式為:
return(表達式);
或者
return表達式;
2012-6-2127
說明:
(1)函數的返回值只能通過return語句返回給
主調函數。在函數中允許有多個return語句,
但每次調用只能有一個return語句被執行,因
此只能返回一個函數值。
(2)返回值的類型和函數定義中函數的類型應
保持一致。如果兩者不一致,則以函數類型為
準,自動進行類型轉換。
(3)系統默認的函數返回值類型為整型,因此
當函數返回值為整型時,在函數定義時可以省
去返回值類型說明。
2012-6-2128
(4)當函數沒有返回值時,函數的返回值類型可以
定義為“空類型”,類型說明符為“void”。在調
用無返回值的函數時,往往是以單獨的調用語句
出現的,即在主調函數中就不能使用被調函數的
函數值了。為了使程序有良好的可讀性并減少出
錯,凡不要求返回值的函數都應定義為空類型。
假設將例5.4中函數fac定義為void,即:
voidfac(intx)
)
則在主函數中寫語句:layer二fac(n);就是錯誤的
2012-6-2129
【例5.5】求兩個數的最大值。
主函數main()與例5.3的相同,max函數改寫如下:
max(intm,intn)
(
if(m>n)
returnm;
else
returnn;
)
函數max的返回值為整型,定義函數時省略了類
型,所以也未對max函數作類型聲明。
2012-6-2130
5.5函數的參數及參數的傳遞
5.5.1函數的參數
1,形式參數(簡稱形參)
在定義函數時函數名后面括弧中的變量名稱為
形參,即形參出現在函數定義中。
形參變量只有在被調用時才為其分配臨時內存
單元,在調用結束時,即刻釋放所分配的內存
單元。因此,形參只在函數內部有效。函數調
用結束返回主調函數后則不能再使用該形參變
量。
2012-6-2131
2.實際參數(簡稱實參)
在調用函數時,函數調用語句中函數名后面括弧
中的參數稱為實參。實參出現在主調函數中。
實參可以是常量、變量、表達式、函數等,無論
實參是何種類型的量,在進行函數調用時,它
們都必須具有確定的值,以便把這些值傳送給
形參。因此應預先用賦值、輸入等辦法使實參
獲得確定值。
實參和形參在數量、類型、順序上應嚴格一致,
否則會發生“類型不匹配”的錯誤。
2012-6-2132
5.5.2參數的傳遞方式
實參和形參的功能是作數據傳送。在c語言中實
參和形參之間的數據傳遞有兩種方式。
1.傳值
調用函數時將實參的值傳遞給形參,形參值的改
變不會影響實參。調用結束后,形參所占用的內
存單元被釋放,實參仍保持原值不變。該方法只
能由實參向形參傳遞數據,即該方式是單向傳遞。
2012-6-2133
【例5.6]傳值方式舉例。
#include<stdio.h>
voidswap(intjnt);/*對被調函數的類型聲明*/
intmain()
(
intn,m;
printf(nPleaseinputnumber:");
scanf("%d%d"5&n,&m);
printf(,,n=%d,m=%d\n,,,n,m);
swap(n,m);
printf("n=%d,m=%d\n",n,m);
return0;
)
2012-6-2134
voidswap(intx,inty)
/*函數swap的定義,該函數無返回值7
(
intt;
t=x;
x=y;
y=t;
printf("x=%d,y=%d\n,,,x,y);
)
假定輸入n和m的值分別為5和7,運行結果如下:
Pleaseinputnumber:57/
n=5,m=7
x=7,y=5
n=5,m=7
2012-6-2135
?本例中函數swap的功能是交換兩個參數的
值。但從運行結果可以看出,調用swap函
數只交換了兩個形參的值,而實參的值并
沒有交換。
5K!75Kg7
5E77?5
(a)調用swap時,形參分別得到對應實參的(b)執行sw叩,交換了形參的
值圖5.1傳值方式疆列
2012-6-2136
【例5.7】利用數組元素、表達式作為實參進行參數傳遞。
#include<stdio.h>
intsum(intjnt);
intmain()
intx=10,y=20,a,bc;
J運行結果如下:
intaa[3]={1,2,3};
x+y=30
a=sum(x,y);
(x+10)=y=40
b=sum(x+10,y);
aa[0]+aa[1]+aa[2]=6
c=sum(sum(aa[0],aa[1]),aa[2]);
printf("x+y=%d\n",a);
printf("(x+10)+y=%d\n",b);
printf("aa[0]+aa[1]+aa[2]=%d\n",c);本例在主調函數main函數中,分別
return0;用零量:x,V、表達式:x+10、數
}組元素:aa[O],aa[1],aa[2]>函
intsum(intm,intn)數值sum(aa[0],aa[1])作為實參單向
給形參傳遞值。
intp;
p=m+n;
returnp;
Joi2-6-21
37
由此可見,在普通變量或數組元素作為函數
參數時,形參變量和實參變量是在程序運
行時分配的兩個不同的內存單元,所進行
的值傳遞是單向的,即只能從實參傳向形
參,不能從形參傳回實參。形參的初值和
實參相同,而形參的值發生改變后,實參
的值并不變化,兩者的最終值是不同的。
2012-6-2138
2,傳地址
在實際應用中,往往需要將形參的值返回給
實參,所以需要雙向傳遞,這時可以使用
傳地址方式。
當用表示地址的數組名或者用指針變量(詳
見第6章)作為函數參數進行參數傳遞時就
不是傳值,實際上傳送的是地址,即把實
參所存放的地址賦予形參。由于形參在調
用時所得到的是實參所指的地址,因而形
參和實參將占用同一片內存空間,即兩者
指向同一個對象,因此在被調函數中對形
參所做的操作都會影響到實參。
2012-6-2139
【例5.8】采用插入排序法將數組中元素升序排列。
#include<stdio.h>
#defineN10
voidsort(inta[],intn);
intmain()
(
ints[N],i;
printf("Pleaseinputdata:");
for(i=0;i<N;i++)
scanf("%d",&s[i]);
sort(s,N);
printf("Thelistis(inmain()):");
for(i=0;i<N;i++)
printf("%4d",s[i]);
return0;
2012-6-2140
voidsort(inta[],intn)
int本例中,排序函數sort(inta[],intn)
for(i=0;i<n-1;i++)的兩個形參中,a表示數組"n
指定數組的長度。
k=i;
for(j=i+1;j<n;j++)
if(a[j]<a[k])k=j;
if(k!=i)
t=a[k];a[k]=a[i];a[i]=t;
}
}
printf("\nThelistis(insort()):");
for(i=0;i<n;i++)
printf("%4d",a[i]);
2012-6-2141
注意:
用數組名作為函數參數時,必須在被調函數與主
調函數中分別定義數組。在對形參數組定義時不
指定數組的長度,而僅給出類型、數組名和一對
方括號,以便允許同一個函數可根據需要來處理
不同長度的數組;但是為了能使程序了解當前處
理數組的實際長度,往往用另一個參數來表示數
組的長度。當多維數組名作為函數參數時,除第
一維可以不指定長度外,其余各維都必須指定數
組長度。形參數組與實參數組在類型上應該一致,
否則會出錯。
2012-6-2142
5.6函數的嵌套與遞歸調用
5.6.1函數的嵌套調用
C語言中不允許作嵌套的函數定義。因此各
函數之間是平行的,不存在上一級函數和
下一級函數的問題。但是C語言允許在一
個函數的定義中出現對另一個函數的調用。
這樣就出現了函數的嵌套調用,即在被調
函數中又調用其它函數。
2012-6-2143
?函數的嵌套調用可以用圖5.2表示,這是一
個二層調用的示意圖。
main函數fl函數f2函數
①②③
⑤
調用fl函數調用f2函數
⑨⑦
結束返回main函數返回fl函數
圖5.2函數嵌套調用示意圖
2012-6-2144
【例5.9]計算1!+2!+3!+…+10!
#include<stdio.h>longsum(intn)longfac(intx)
longfac(int);
longsum(int);inti;longy;
intmain()longm=0;inti;
for(i=1;i<=n;i++)y=1;
longs;m+=fac(i);for(i=1;i<=x;i++)
s=sum(10);returnm;y=y*i;
printf("1!+2!+..+10!=%ld",s);}returny;
return0;}
)
2012-6-2145
5.6.2函數的遞歸調用
在調用函數的過程中又出現直接或間接的調用該函數自身,稱為
函數的遞歸調用。這種函數稱為遞歸函數。C語言允許函數的
遞歸調用,但是程序中不應出現無終止的遞歸調用,只應出現
有限次數的。
例如有函數fun如下:
intfun(intm)
intn;
t=fun(n);
returnt;
這個函數是一個遞歸函數。但是運行該函數時將無休止地調用其
自身,這顯然是不正確的。為了防止遞歸調用無終止地進行,
必須在函數內有終止遞歸調用的語句。常用的辦法是加條件判
斷,滿足某種條件后就不再作遞歸調用,然后逐層返回。
2012-6-2146
【例5.10】用遞歸算法計算n!
用遞歸法計算n!可用下述公式表示:
n!=1(n=0,1)
nX(n-1)!(n>1)intmain()
include<stdio.h>intn;
longfac(intn)longm;
printf(H\nPleaseinputainteger:");
scanf(”%cT,&n);
longf;
m=fac(n);
if(n==0||n==1)f=1;printf(,,%d!=%ld,,,n,m);
elsef=n*fac(n-1);return0;}
returnf;
)
2012-6-2147
57變量的作用域和存儲類型
前面介紹了變量的一些屬性及使用方法,本節將從
空間和時間兩個不同的角度來描述變量,介紹變
量的作用域和生存期。兩者既有聯系,又有區別
變量的作用域指一個變量能夠起作用(被引用)的
程序范圍,即一個變量定義之后,在何處可以使
用該變量。
變量的生存期指程序在執行期間,變量存在的時間
間隔,即從給變量分配內存,至所分配內存被釋
放的那段時間。
2012-6-2148
5.7.1變量的作用域
c語言中所有的變量都有自己的作用域。變量
定義的位置,其作用域將不同。C語言中的變
量,按作用域范圍可分為兩種,即局部變量和
全局變量。
1.局部變量
局部變量也稱為內部變量。局部變量是在函數
內作定義說明的。其作用域僅限于函數內,離
開該函數后再使用這種變量是非法的。
2012-6-2149
例如:
intf1(inta)/*函數f1*/
{/*a,b,c在該花括號范圍內有效*/
intb,c;
)
intf2(intx)/*函數f2*/
{/*x,y,z在該花括號范圍內有效*/
inty,z;
)
intmain()
{/*在該花括號范圍內有效*/
2012-6-2150
說明:
(1)主函數中定義的變量也只能在主函數中使用,
不能在其它函數中使用。同時,主函數中也不能
使用其它函數中定義的變量。因為主函數也是一
個函數,它與其它函數是平行關系。
(2)形參變量是屬于被調函數的局部變量,實參變
量是屬于主調函數的局部變量。
(3)允許在不同的函數中使用相同的變量名,它們
代表不同的對象,分配不同的單元,互不干擾,
也不會發生混淆。如在例5.10中,形參和實參的
變量名都為n,是完全允許的。
2012-6-2151
(4)在復合語句中也可定義變量,其作用域只在復合語句
范隹I內。
例如:
main()
{/*s,a在該對花括號范圍內有效*/
ints,a;
{/*b在該對花括號范圍內有效7
intb;
s=a+b;
}
)
2012-6-2152
【例5.11】局部變量作用域舉例。
#include<stdio.h>
intmain()
inti=1,j=2,k;/*4行,ij,k為main函數內定義的局部變量
k=i+j;
(
intk=5;/*第7行,k為復合語句內定義的局部變量*/
printf(,,k=%d\n,,,k);
)
,,,,
printf(i=%d,j=%d,k=%d\n,i,j,k);運行結果如下:
return0;
k=5
)i=1,j=2,k=3
2012-6-2153
2.全局變量
全局變量也稱為外部變量,它是在函數外部
定義的變量。它不屬于哪一個函數,它屬
于一個源程序文件。其作用域是整個源程
序。在函數中使用全局變量,一般應作全
局變量說明。只有在函數內經過說明的全
局變量才能使用。全局變量的說明符為
externo但在一個函數之前定義的全局變量,
在該函數內使用可不再加以說明。
2012-6-2154
例如:
inta,b;/*a,b為全局變量*/
voidf1()
)
floatx,y;/*x,y為全局變量*/
intf2()
)
intmain()/*主函數*/
}
2012-6-2155
【例5.12】輸入半徑,求圓的面積和周長。
#include<stdio.h>
#definePI3.14
floatcircle;/*定義全局變量circle,用來獲取周長*/
floatf(floatr)
intmain()
floats;
s=PI*r*r;floatr,area;
printf("\nPleaseinputr:");
circle=2*PI*r;
scanf("%f',&r);
returns;
area=f(r);
)printf("area=%f,len=%f\n",area,circle);
return0;
)
2012-6-2156
關于全局變量的使用,還需注意:
(1)全局變量可加強函數模塊之間的數據聯系,
但是又使函數要依賴這些變量,因而使得
函數的獨立性降低。從模塊化程序設計的
觀點來看這是不利的,因此在不必要時盡
量不要使用全局變量。
(2)在同一源文件中,允許全局變量和局部變
量同名。在局部變量的作用域內,全局變
量不起作用。
2012-6-2157
【例5.13】全局變量和局部變量同名舉例。
include<stdio.h>
inta=1,b=2;/*全局變量a,b*/
intsum(intx,inty)
(intmain()
intz;
(
z=x+y;inta=5;/*局部變量a*/
returnz;printf("a+b=%d,,,sum(a,b));
)return0;
}
運行結果如下:
a+b=7
2012-6-2158
5.7,2變量的存儲類型
1.動態存儲方式與靜態存儲方式
在C語言中,變量不僅具有確定的數據類型要求,
而且還有存儲類型的要求。變量的存儲類型是其
存儲屬性,即變量在內存中的存儲方式,不同的
存儲方式,將影響變量值的存在時間(即生存
期)。變量的存儲方式可分為“靜態存儲”和
“動態存儲”兩種。
靜態存儲方式:指在變量定義時就分定存儲單元并
一直保持不變,直至整個程序結束。
動態存儲方式:指在程序執行過程中,使用它時才
分配存儲單元,使用完畢立即釋放。
2012-6-2159
用戶存儲空間可以分為三個部分:程序區、靜態存
儲區、動態存儲區。
全局變量全部放在靜態存儲區,在程序開始執行時
給全局變量分配存儲區,程序執行完畢就釋放。
動態存儲區存放以下數據:
(1)函數的形式參數;
(2)自動變量(未加static聲明的局部變量)
(3)函數調用時的現場保護和返回地址。
這些數據在函數開始調用時分配動態存儲空間,函
數結束時釋放這些空間。
2012-6-2160
因此,在C語言中,每個變量有兩個屬性:數據類型和數據
的存儲類型。一個變量說明的完整形式應為:
存儲類型標識符數據類型標識符變量名,變量名…;
在c語言中,對變量的存儲類型說明有以下四種:
auto自動變量
register寄存器變量
extern外部變量
static靜態變量
例如:
staticinta,b;說明a,b為靜態類型變量
autocharc1,c2;說明c1,c2為自動字符變量
staticinta[5]={123,4,5};說明a為靜態整型數組
externintx,y;而明x,y為外部整型變量_
2012-6-2161
2.四種存儲類型
(1)auto變量
函數中的形參利在函數內定義的未加存儲類型標
識符的局部變量(包括在復合語句中定義的變量)
均視為自動變量,也就是說自動變量反省去說明
符aut。。在調用函數時系統將給自動變量分配存
儲空間,函數調用結束時就自動釋放空間。例如:
intf(intx)
inty;
autointz;
)
形參x和局部變量y、z都是自動變量。
2012-6-2162
(2)用static聲明局部變量
若希望函數中的局部變量的值在函數調用結束后不消失而
保留原值,這時就應該指定局部變量為“靜態局部變量”
用關鍵字static進行聲明。
說明:
①靜態局部變量屬于靜態存儲類別,在靜態存儲區內分配存
儲單元。在程序整個運行期間都不釋放。而自動變量(即
動態局部變量)屬于動態存儲類別,占動態存儲空間,函
數調用結束后即釋放。
②靜態局部變量在編譯時賦初值,即只賦初值一次;而對自
動變量賦初值是在函數調用時進行,每調用一次函數重新
賦一次初值,相當于執行一次賦值語句。
③如果在定義局部變量時不賦初值的話,則對靜態局部變量
來說,編譯時自動賦初值0(對數值型變量)或空字符
(對字符變量)。而對自動變量來說,如果不賦初值則它
的值是一個不確定的值。
2012-6-2163
【例5.14】打印1到4的階乘值。
#include<stdio.h>
intfac(intn)
(
staticintf=1;
f=f*n;
returnf;
}
intmain()
(
inti;
for(i=1;i<=4;i++)
printf("%d!=%d\n",i,fac(i));
return0;
}_.................
2012-6-2164
(3)register變量
為了提高效率,C語言允許將局部變量的值放在
CPU中的寄存器中,這種變量叫“寄存器變量”,
用關鍵字register作聲明。
說明:
①只有局部自動變量和形式參數可以作為寄存器變
量;
②一個計算機系統中的寄存器數目有限,不能定義
任意多個寄存器變量;
③局部靜態變量不能定義為寄存器變量。
2012-6-2165
【例5.15】使用寄存器變量。
intfac(intn)
(
registerinti,f=1;
for(i=1;i<=n;i++)
f=f*i
returnf;
)
intmain()
(
inti;
for(i=0;i<=4;i++)
printf("%d!=%d\n",i,fac(i));
return0;
)
2012-6-2166
(4)用extern聲明全局變量
全局變量是在函數的外部定義的,它的作用域為從
變量定義處開始,到本程序文件的末尾。如果全局
變量不在文件的開頭定義,其有效的作用范圍只限
于定義處到文件結束。如果在定義位置之前的函數
要引用該全局變量,則應該在引用之前用關鍵字
extern對該變量作“全局變量聲明”。表示該變量
是一個已經定義的全局變量。有了此聲明,就可以
從“聲明”處起,合法地使用該外部變量。
2012-6-2167
【例5.16】
#include<stdio.h>
intsum(intx,inty)
intz;
運行結果如下:
z=x+y;
returnz;30
}
intmain()
externA,B;
printf("%d\n",sum(A,B));
return0;
}
intA=10,B=20;
2012-6-2168
5.8綜合實例
【例5.17】通過鍵盤輸入10個整數,求最大
值和最小值及平均值。
方法1:將10個整數放在一個數組中,作為一個
整體來處理。分別用三個函數來求最大值、最小
值、平均值。
2012-6-2169
#include<stdio.h>
#defineN10
intmax(inta[],intn);
intmin(inta[],intn);
floatave(inta[],intn);
intmain()
inta[N],i,max_a,min_a;
floatave_a;
printf("Pleaseinput10integer:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
max_a=max(a,N);
min_a=min(a,N);
ave_a=ave(a,N);
printf("Themaxis:%d\n",max_a);
printf("Theminis:%d\n",min_a);
printf("Theaverageis:%f\nn,ave_a);
2012-6-2170
rn
intmax(inta[],intn)
intmin(inta[],intn)
inti,m;
inti,m;
m=a[0];
m=a[0];
for(i=1;i<n;i++)
for(i=1;i<n;i++)
if(m<a[i])m=a[i];
if(m>a[i])m=a[i];
returnm;
returnm;
)
)
floatave(inta[],intn)
inti;
floatm=0;
for(i=0;i<n;i++)
m+=a
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 名義股東入股協議書
- 貨場搬運協議書范本
- 物品領取寄存協議書
- 詳細參見技術協議書
- 學生頂崗管理協議書
- 同意安裝暖氣協議書
- 私人安裝門窗協議書
- 景觀樓梯購買協議書
- 水泥授權代理協議書
- 刑事和解協議書公司
- 2025江西南昌市江銅產融社會招聘1人筆試參考題庫附帶答案詳解
- 110KV 線路保護調試報告
- 移動設備小型設備施工方案
- 臨床思維診療訓練系統參數
- 揚州市巡游出租汽車駕駛員從業資格區域科目考試題庫(含答案)
- DB37-T 3466-2018人民防空工程防護(化)設備維護保養規程
- (完整版)建筑構造課件
- 《巖石力學(含實驗)》課程教學大綱
- 中國銀行保函業務培訓(共71頁).ppt
- 廣東公共就業服務標準化手冊
- 全國油料高產創建測產驗收辦法
評論
0/150
提交評論