《C語言程序設計》課件第6章_第1頁
《C語言程序設計》課件第6章_第2頁
《C語言程序設計》課件第6章_第3頁
《C語言程序設計》課件第6章_第4頁
《C語言程序設計》課件第6章_第5頁
已閱讀5頁,還剩123頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

語言程序設計添加副標題C

Programming第6章 模塊化程序設計與函數2找前5個默尼森數。P是素數且M也是素數,并且滿足等式M=2P-1,則稱M為默尼森數。例如,P=5,M=2P-1=31,5和31都是素數,因此31是默尼森數。3int

main(){int

prime(int

x){int

i,p,count=0;for(p=2;count<5;p++)if(prime(p)&&int

i;double

r;r=sqrt((double)x);for(i=2;i<=r;i++)if(x%i==0)return

0;return

1;}prime(pow(2,(double)p)-1)){

printf("%5d",p);count++;}return

0;}函數0

140

2構成部分0

3每部分要 素0

4使用函數的目的5思考對于建立函數的主要目的,以下說法正確的是_

_B

(B)提高程序的可讀性和可維護性(A)提高程序的執行效率(C)減少程序的篇幅(D)減少程序文件所占的內存以下正確的說法是

B用戶若需調用標準庫函數,調用前必須重新定義(B)用戶可以重新定義標準庫函數,若如此,該函數將失去原有含義(C)系統根本不允許用戶重新定義標準庫函數(D)用戶若需調用標準庫函數,調用前不必使用預編譯命令將該函數所在文件包含到用戶源文件中,系統自動去調用主要內容66.1

函數概述76.1.1模塊化程序設計8大規模程序開發策略——模塊化模塊化程序開發基本步驟(自1自)頂設向計向階下段(2)編碼階段自底向上模塊化策略開發程序的優點從整體上簡化概念結構,降低程序開發和修改的復雜度,提高程序易讀性。6.1.2函數9函數是什么將一組語句封裝為一個獨立代碼塊的實現方法。maincabd與函數有關的3個語法概念–函數定義–函數調用–函數返回函數10#include

<stdio.h>void

printstar(){printf("*

*

*

*

*

*

*

*

**\n");}void

print_message(){printf("How

do

you

do!\n");}int

main(){printstar();print_message();printstar();return

0;}函數11#include

<stdio.h>int

max(int

x

,

int

y){int

z;z=x>y?x:y;return(z);}int

main(){int

a,b,c;scanf("%d,

%d",&a,&b);c=max(a,b);printf("Max

is

%d\n",

c);return

0;}011

26.2.1函數定義形式02036.2.2函數名0405?6

.

2

.

3函數返回值類型?6

.

2

.

4函數的形式參數?6

.

2

.

5函數體?6

.

2

.

6函數的存儲類型6.2函數定義13返回值類型6.2.1

函數定函數義名

形形式參式數聲明int

min(int

x,int

y)/*函數首部*/{/*函數體開始*//*局部變量聲明*/int

z;z=x<y?

x:y;return

z;/*語句/*語句*/*/}/*函數體結束*/6.2.1

函數定義形式14函數定義一般形式[存儲類型說明符][返回值類型說明符]函數名([形式參數聲明表]){聲明序列語句序列}6.2.2函數名15函數名是函數的標識,按標識符命名規則確定。自定義的函數名:–不允許與同一源程序中其它自定義函數同名,允許與庫函數同名;int

f(int

x){……}intsqrt(int

x){float

f(int

x)return

x+2;{in…t…ma}in(){……}}int

main(){……}首部{4printf("x

=

%d",x);}51612定義無返回值函數時返回值類型說明符為void例如:3首部66.2.3返回值類型void

print_value(int

x)6.2.3返回值類型17如果不寫?定義有返回值函返數回值時類型必說明須符位在置給出返回值的數據類型。例如:C89標準允許省略返回值類型說明符,省略時編譯系統假定函數的返回值類型為int。int

f(int

x){return

(x+2);}首部6.2.4形式參數18形式參數是一個函數與其他函數之間傳遞數據的接口定義無參函數時形式參數聲明為void或空例如:void

print_word(void)

/*

void

print_word(

)

*/{printf("hello");}首部6.2.4形式參數19定義有參函數時形式參數的一般聲明形式存儲類型說明符數據類型說明符形式參數名表示形式參數的存儲屬性,允許省略。首部int

f(int

x,int

y){int

f(int

x,

y){…………}}int

f()int

x,y}y};……{6.2.4形式參數20形式參數名:是形式參數的標識,僅在該函數體內使用,在其他函數中不可見。不允許在一個函數中定義同名的多個形式參數,允許在 不同函數中定義同名的形式參數。int

f(intx){int

f(int

x,int

x){……float

x;

……}i}nt

main(){int

x;……}}i}int

main(){……}首部2

1數據類型說明符:–指定形式參數的數據類型。–形式參數允許:針結構類型聯合類型枚舉類型數組類型基本類型指函數類型類型首部6.2.4形式參數6.2.5函數體22函數體——{}C89要求所有聲明必須出現在第一條語句之前,C99則允許分散的聲明和語句。例如:int

main(void){

int

a;a=1;int

b;/*

C89報錯,C99正確*/for(int

i=1;i<10;i++)/*

C89報錯,C99正確*/a*=i;return

0;}0

10

20

30

40

52

4函數返回通過r

e

t

u

r

n語句實現

r

e

t

u

r

n語句的三個用途–結束函數的執行并返回到主調函數0

60

70

80

9–向主調函數傳遞回一個函數類型的返回值;–歸還函數中定義的局部對象的存儲空間6.3函數返回6.3函數返回25return語句的兩種形式return

(e);返回主調函數并將e值帶回主調函數–非void類型函數用"return(e);"完成返回操作并將e值帶回主調函數。return;返回主調函數–void型函數用"return;"完成返回操作;–函數體結束的右花括號等同于一個"return;"語句。–e:返回值表達式,圓括號可省略。數據類型允許是基本類型、指針類型、結構類型、聯合類型、枚舉類型。6.3函數返回26C89允許非void類型函數中使用"return;"返回,對于int型函數將返回給主調函數0值;對于其他類型函數將返回一個不確定的值。print_value(int

x){printf("x

=

%d",x);}C99規定非void類型函數必須使用"return(e);"返回。6.3函數返回27函數體中無return語句時,函數仍然帶回一個不確定的值。print_message(){printf("How

do

you

do!\n");}int

main(){

int

a;a=print_message();printf("%d\n",a);return

0;}6.3函數返回28若要求"不帶回值",可以用"void"定義"無值類型"(或稱"空類型"),禁止其帶回值。這時的函數是純過程型的。若將上例前部改為:void

print_message(){..

..}系統將禁止在調用函數中使用被調用函數的返回值。如此,下面的用法就是錯誤的,編譯時就會報告出錯信息。a=print_message();6.3函數返回29一個函數是否有返回值及返回值類型的決定因素是函數定義時的返回值類型說明符。函數每次調用后返回的值由"return(e);"語句決定。允許"return(e);"中e的類型與返回值類型說明符不同,但兩者應賦值兼容。例如:int

f(double

x){

return

x*x;

}最終f函數返回一個?類型值給主調函數。30不能通過

return語句返回多個值給主調函數例如:int

f(

intx,

int

y){123654f函數被調用時總是返回y的值}return

(

x,

y);6.3函數返回6.3函數返回32main函數的特殊性–函數名不能自定義;既允許帶形式參數也允許不帶形式參數。若有其形式參數,其數量和類型不能隨意定義;函數首部:C89允許"intmain()"、"main()"或"voidmain()"; C99規定必須為"int

main()"。程序開始運行時main函數首先被操作系統調用;執行到main函數 中任一return語句或函數體結束右花括號時,結束程序運行。6.4

函數調用336.4函數調用34一個函數調用另一個函數意味著將程序執行流程轉移到被調用函數。正確實現函數間相互調用必須滿足以下條件–被調用函數存在且允許被調用;給出滿足被調函數運行時要求的參數值;在調用函數前對被調用函數做引用性聲明;按指定格式調用。6.4.1

函數的引用性聲明35引用性函數聲明的目的擴大函數名的作用域

為編譯系統提供被調函數的形式參數和返回值信息,使得編譯系統可以對隨后出現的所有對該函數調用的參數與返回值作一致性檢查并作適當的類型轉換。函數引用性聲明通常被稱為"函數原型"6.4.1函數的引用性聲明36庫函數的引用性聲明(函數原型)–分類保存在一組系統頭文件中。例如:#include<math.h>…

…double

sqrt(double

x);sqrt()6.4.1函數的引用性聲明37自定義函數的引用性聲明(函數原型)int

max(int

x,int

y){

int

z;int

max(intx,

int

y);if(x>y)z=

x;int

max(int,int);elsez=y;return

z;}01020304函數的引用性聲明函數引用性聲明一般形式38存儲類型說明符返回值類型說明符函數名(形式參數類型表);形式參數類型表中形式參數允許有兩種形式:數據類型05數據類型參數名6.4.1

函數的引用性聲明39函數定義本身也是函數聲明結論:若將函數定義放在該函數所有調用之前則不需要該函數的引用性聲明。#include

<stdio.h>void

max(int

x,int

y){int

temp;temp=x;

x=y;

y=temp;}int

main(void){int

a=1,b=2;max(a,b);printf("a=%d,b=%d",a,b);return

0;}6.4.1

函數的引用性聲明40#include

<stdio.h>int

main(void){int

a=1,b=2;max(a,b);prrinetf(t"a=u%d,rb=%nd",a,b0);;}C99Error:

Typemismatch

inredeclarationof

"max"C89void

max(int

x,int

y){E

rro

r:

externint

"max"int

temp;temp=x;

x=y;

y=temp;}6.4.2函數調用41直接函數調用用函數名、圓括號及實在參數表達式表調用函數的形式例1:聲明為"double

pow(double

x,double

y);""pow(2,3)"是pow函數的一種直接調用形式0

5p

r

i

n

t

_

w

o

r

d

(

)

;i

n

t

m

a

i

n

(

v

o

i

d

·

·

·

·{}0

6v

o

i

d

p

r

i

n

t

_

w

o

r

d

(

v

o

i

d

){0

3自定義函數p

r

i

n

t

_

w

o

r

d的定義為}0

44

20

1例2:0

26.4.2函數調用printf("hello");43無參函數直接調用一般形式函數名()有參函數直接調用的一般形式函數名(實在參數表達式表,…,…)函數名(實在參數表達式表,…,…)6.4.2函數調用6.4.2函數調用44非void型函數調用函數調用表達式語句–函數調用作為其它表void型函函數數調調用用不能作為運算分量出現其它表達式中y=pow(2,3達式的運算);分量pow(2,3);例如:對于以v下oid函p數rin定t_v義alue(int

x){print_value(2);printf("x

=

%d",x);y=print_value(2);}函數例1問題45輸出以下形式(

printstar()函數輸出一行星號,print_message()函數輸出字符串"How

do

you

do!")*

*

*

*

*

*

*

**

*H*o*w

*do*

y*ou*

d*o!**

*46舉例1#include<{stdipori.nht>f("*

*

*

*

*

*

*

*

*

*\n");v}oidpvoriidntstar(

)print_message(

){printf("How

do

youdo!\n");}int

main(){

printstar();print_message();printstar();return

0;}函數例2問題#include

<stdio.h>47int

max(int

x,int

iyf)

(x>y)return

x;{}elsereturnint

main()y;{

int

a,b;scanf("%d,

%d",&a,&b);printf("Max

is

%d\n",

max(a,b));return

0;}函數例3問題48#include

<stdio.h>int

main(){

flsocoaantf("%f,%f",&a,

add&(bf)l;oat,floca=ta)d;d(a,b);}prifnltofa(t"sau,mb,ics;%若不加函數引用性聲明的結果是?float

add(float

x,{floaftl\onya")t,c);zr;eturn

0;z=x+y;return(z);}490

1間接調用0

2直接調用0

3To

becontinued0

4函數調用6.4.3函數調用時的參數傳遞50調用一個有參函數的執行過程對實參表中所有實參表達式求值為被調函數的所有形式參數分配存儲空間檢查每個實參值的類型與對應形參數據類型是否相同,若不同則將實參類型轉換為形參要求的類型將實參值復制給形參(形參=實參,參數傳遞)

(5)轉入被調函數執行6.4.3函數調用時的參數傳遞51函數調用時參數傳遞的類型傳遞數值(值傳遞)形式參數的數據類型是基本類型,函數調用時傳遞給 該形參的實參應是與形參兼容的基本類型數據。若實參數據類型級別高于形參數據類型,對實參值做類型轉換時會產生轉換誤差,出現數據損失。6.4.3函數調用時的參數傳遞52#include

<stdio.h>int

max(int

x

,

inty){

int

z;z=x>y?x:y;intmain()return(z);}{

int

a,b;scanf("%d,

%d",&a,&b);printf("Max

is

%d\n",

max(a,b));return

0;}程序功能:從鍵盤接收4對正整數,求出每對數的最大公約數,將這些公約數相加并保存到s1,再將這些公約數中的素數相加并保存到s2。例如當輸入為6

8

6

9

8

12

5

10時,輸出結果為53s1#=14,is2=n10。clude<stdio.h>#include<math.h>int

gcd(int

x,int

y);int

prime(int

x);int

main(){int

i,a,b,c,s1=0,s2=0;for(i=0;i<4;i++){c=gcd(a,b);scanf("%d%d",&a,&b);s1=s1+c;if(prime(c))

s2+=c;}printf("s1=%d,s2=%d",s1,s2);return

0;}54函數int

gcd(int

x,int

y)

int

prime(int

x){{int

i;for(i=2;i<=sqrt(x);i++)if(x%i==0)return

0;int

r;while(r=x%y){

x=y;y=r;}return

y;return

1;}}驗證歌德巴赫猜想:任何一個大于4的偶數都55可以表示為兩個素數之和。驗證6-50之間的偶數for(i=6;i<=50;i+=2){for(n1=3;n1<=i/2;n1+=2)if(prime(n1)){if(prime(n2))n2

=

i-n1;break;}if(n1>i/2){

printf("error\n");break;}elseprintf("%d,%d\n",n1,n2);}函數調用時的參數傳遞56傳遞函數地址傳遞地址傳遞數值To

be

continued6.4.5

遞歸函數570

10

20

30

458初步認識遞歸函數n!的計

算可定義為:10

50

60

7(n=0或n=1)n!=n×(n-1)!(n>1)6.4.5遞歸函數6.4.5遞歸函數59計算n!函數long

f(long

n)/*基本問題判斷及計算結果*/{

if(n==1)return

1;elsereturn

n*f(n-1);/*簡化問題,遞歸調用*/}6.4.5遞歸函數特點60用遞歸函數解決復雜問題時,每次遞歸調用時要解決的問題都要比上次的調用簡單,數據規模越來越小,最終到達最小數據規模(基本問題)。解決完基本問題后,函數沿著調用順序逐級返回上次調用一個結果值,直到函數的原始調用處為止。遞歸函數一般由一個選擇結構組成:條件為真的部分,計算基

本問題終止遞歸調用;條件為假的部分,簡化問題繼續遞歸調用。遞歸函數的每次調用系統都為函數的所有動態變量(形式參數和動態局部變量)分配本次調用使用的存儲空間,直到本次調用結束返回時方才釋放。遞歸函數執行過程610

10

20

30

40

50

66

25

!1

2

0*

4

!四.四.**23

!3

*

2

!0

70

80

91

01

1回歸遞推*

12

*

1

!1遞歸函數執行過程6.4.5遞歸函數63例1:求Fibonacci數問題。F(0)=0,

F(1)=1,

F(n)=F(n-1)+F(n-2)#include

<stdio.h>long

fibonacci(int

n){

if(n==0||n==1)

return

n;else

return

fibonacci(n-1)+fibonacci(n-2);}int

main(void){

}求fibonacci(5)過程646.4.5遞歸函數65例2:用輾轉相除法求兩個整數的最大公約數。#include

<stdio.h>int

gcd(int

a

,int

b){

int

r

;if((r=a%b)==0)return

b;elsereturn

gcd(b,r);}int

main(void){

printf("%d",gcd(25,30));}6.4.5遞歸函數66例3:用二分法求方程-3x3

+4x2

-5x+6=0在[1,2]中的一個近似根,允許誤差10-6

。d{ourbelteurfn(d6o-uxb*l(e5-x*)(4-3*x));

}double

root(double

a,double

b){

double

c;int

main(void){…root(1,2);

}if(fabs(f(a))<1e-6)

return

a;if(fabs(f(b))<1e-6)

return

b;c=(b+a)/2;if(fabs(f(c))<1e-6)

return

c;if((f(c))*f(a)<0)

return

root(a,c);else

return

root(c,b);}例4:Hanoi塔問題67有3個底座(分別標記為A、B和C),A座上已從大到小依次疊放了64個大小不同的盤子,要求將A座上的盤子全部搬到C座上。在搬運過程中可以借助于B座,每次只能搬一個盤子,任何時候每個底座上的盤子都必須保持大盤在下小盤在上的疊放順序。例4:Hanoi塔問題68例4:Hanoi塔問題69#include

<stdio.h>void

Hanoi

(int

n,

char

A,

char

B,

char

C){if(n==1)printf("\n

move

%d

from

%c

to

%c",

n,A,C);else{

Hanoi

(n-1,A,C,B);printf("\nmove

%d

from

%c

to

%c",

n,A,C);Hanoi

(n-1,B,

A,

C);}}int

main(void){

Hanoi

(3,

"A"

,

"B"

,

"C"

);return

0;}例4:Hanoi塔問題70初學者編寫遞歸函數時常犯錯誤

71⑴缺少對數據最小規模的正確判斷、處理及返回操作。函數一旦被調用將進入無窮遞歸。例如:long

f(long

n){return

n*fact(n-1);}初學者編寫遞歸函數時常犯錯誤72(2)函數遞歸調用時所用的數據規模不小于本次函數被調用時的數據規模。函數一旦被調用也將進入無窮遞歸。例如:long

f

(long

n){if

(n<=1)return

1;elsereturn

n*fact

(n);}例5:把一個整數作為字符串打印出來。算法:把字符串看作一個字符與長度大于1的字符串的并置,用遞歸函數p

r

i

n

t

d來處理。17

32#

i

n

c

l

u

d

e

<

s

t

d

i

o

.

h

>v

o

i

d

p

r

i

n

t

d

(

i

n

t

n

){

i

f

(

n

<

0

){

p

u

t

c

h

a

r

(

"

-

"

)

;

n

=

-

n

;

}i

f

(

n

/

1

0

)p

r

i

n

t

d

(

n

/

1

0

)

;p

u

t

c

h

a

r

(

n

%

1

0

+

"

0

"

)

;}3若n為-1

2

3,分析打印過程46.4.5遞歸函數例6:把一個10進制數轉換成base74v進oi制d

輸f(出int

num,intbase){if(num>=base)f(num/base,base);printf("%d",num%base);}int

main(){int

x,y;scanf("%d,%d",&x,&y);f(x,y);return

0;}x2

x375計算sx...

2!

3!xnn!#include

<stdio.h>double

f1(double

x

,

int

n){

double

s=0

,

t=1

;int

k

;用遞推法計算for(k=1;

k<=n;

k++){t*=x/k;s+=t;}return

s

;}int

main(void){printf

(

"%lf\n",

f1(

2

,

4));return

0;

}x2

x376計算sx...

2!

3!xnn!#include

<stdio.h>#include

<math.h>long

f(int

n){

int

i,

s=1;for(i=1;i<=n;i++)

s*=i

;return

s

;用遞歸法計算}double

f1(double

x,

int

n){

if(n==1)

return

x;else

return

f1(x,

n-1)+pow(x,n)/f(n);}int

main(void){

printf("%lf\n",

f1(2,4));

return

0;

}比較遞推法和遞歸法77遞推法–使用循環結構實現循遞歸–法使用選擇結構實現循環環–循環執行函數中的一–循環執行整個函數體段代碼(循環語句)代碼(循環調用)7901#include

<stdio.h>void

fun(int

x){02if

(x/2>0)03fun(x/2);04}05int

main(void){

fun(20);return

0;}06閱讀程序1printf("%d",x%2);8

0i

n

t

f

(

i

n

t

a

,

i

n

t

b

){i

f

(

a

=

=

b

)r

e

t

u

r

n

a

;e

l

s

e

i

f

(

a

>

b

)r

e

t

u

r

n

f

(

a

-

b

,

b

)

;e

l

s

er

e

t

u

r

n

f

(

a

,

b

-

a

)

;}閱讀程序2閱讀程序381int

mystery(int

a,int

b){if(b==1)return

a;elsereturn

a+mystery(a,b-1);}int

main(void){

int

x=5,y=5;printf("%d\n",

mystery(x,y));return

0;}6.5

標識符的作用域828

3代表程序中的各類對象標識符的作用域個代碼段。標識符(

i

d

e

n

t

i

f

i

e

r

)–與已定義或聲明的標識符相關的一–在這個代碼段內使用該標識符是合法的,在這個代碼段外使用該標識符是非法的。0103050204066.5標識符的作用域6.5標識符的作用域84標識符的類型變量名:代表一個值可改變的數據量數組名:代表一組值可改變的數據量起始地址函數名:代表一個函數在內存的存儲位置數據類型說明符:代表一個系統預定義、自定義或用typedef定義的數據類型宏名:代表一個常量或一組語句語句標號:代表一條語句的位置標識符的作用域18

52各類標識符的四類作用域3文件作用域4–從標識符定義或聲明位置起到源文件結尾的源文件范圍5–文件作用域標識符:外部對象名全局變量名6全局數組名7函數名8在函數外自定義的數據類型名9–一個文件作用域標識符的作用域可通過引用性聲明被擴大1

0866.5.1

標識符#includ的e

作用域<stdio.h>int

x;//引用性聲明xvoid

f()//定義f{printf(“%d”,x*x);//使用x}int

main(){x=1;//使用xf();//使用freturn0;}int

x=1;//外部變量x的定義標識符的作用域8

7外部變量定義性聲明與引用性聲明的差別–定義性聲明一個外部變量時可以帶有初始化值也可以不帶初始化值,引用性聲明一個外部變量時不能指定初始化值;–定義性聲明一個外部變量時可以使用存儲類型e

x

t

e

r

n、s

t

a

t

i

c或缺省,引用性聲明一個外部變量時使用存儲類型e

x

t

e

r

n或缺省。6.5.1

標識符的作用域88函數作用域一個函數定義覆蓋的區域函數作用域標識符:語句標號函數作用域總是嵌入在文件作用域內。一個文件作用域內可能包含多個函數作用域。6.5.1

標識符的作用域89塊作用域函數體內一個代碼塊(復合語句)覆蓋的范圍塊作用域標識符:函數定義中出現的形式參數名,局部變量名形式參數名作用域:聲明所在函數體代碼塊內局部變量名作用域:聲明所在代碼塊內塊作用域總是嵌入在函數作用域內。一個塊作用域內還可以包含多個塊作用域。01標識符的作用域029091int

main

(

void){inta=

3

;{intb=

4

;loop:

a++;}if(

a<

6

)

goto

loop;printf("%

d",

b);return

0

;}函數作用域

vs塊作用域6.5.1標識符的作用域92函數原型作用域–函數原型(引用性函數聲明)覆蓋的范圍。函數原型作用域標識符:函數原型中出現的形式參數名例如int

might

(int

small,

doublesmall和large的作用域僅到該行的分號標識符的作用域規則93不允許在同一作用域內定義或聲明代表不同對象的兩個或多個同名標識符。例如:#include

<stdio.h>iinntt

ff=(0i;ntx)/*編譯報錯:重復聲明f

*/{int

x;}/*編譯報錯:重復聲明x*/{

int

x=f(1);

returnint

main(void)0;

}9

401允許在不同的作用域內定義或聲明代表不同對象的兩個或多個同名的標識符。02例如:03#

i

n

c

l

u

d

e

<

s

t

d

i

o

.

h

>i

n

t

f

(

)04{

i

n

t

y

;

}05i

n

t

m

a

i

n

(

v

o

i

d

){

i

n

t

y

;

r

e

t

u

r

n

0

;

}06標識符的作用域規則標識符的作用域規則95內層屏蔽外層當一個作用域內包含了另一個作用域,允許內層作用域和外層作用域中分別聲明代表不同對象的兩個同名標識符。內層作用域中訪問的同名標識符是內層作用域中定隱蔽而不可訪問。#include

<stdio.h>vinotidx=f0(;);intmain(void){

int

x,

loop=0;loop:

for(x=1;x<5;x++){

int

x=2;printf("%d

",x);}void

f(pr)intf("%d

",x);f();

loop++;{printf("%d

",x++);return

0;義}的標識符,此時if(loop<1)

goto

loop;外層作用域中定義}的同名標識符在內*

6.5.2外部對象的連接屬性96在一個多文件程序中,外部對象名(函數名,外部變量名)具有其他標識符不具備的兩個特殊屬性:⑴在使用之前既需要定義也需要引用性聲明

–一個外部對象名只允許在一個源程序中定義一次,但允許在定義所在的源文件或其他源文件中被多次地引用性聲明。6.5.2外部對象的連接屬性97⑵在多文件程序中定義的一個外部對象名具有連接屬性內部連接:僅允許在對象定義所在源文件內使用該對象標識符外部連接:允許在組成一個源程序的所有源文件內使用該對象名定義外部對象連接屬性時使用存儲類型說明符extern(外部連接)和static(內部連接)缺省存儲類型說明符時系統默認為extern。9

8在一個多文件程序中將一個已定義的具有外部連接屬性的標識符作用域從定義所在的源文件擴展到其他源文件的方法是:在其他源文件中引用性聲明該標識符。函數引用性聲明一般形式e

x

t

e

r

n返回值類型說明符函數名(形式參數類型表);全局變量引用性聲明一般形式e

x

t

e

r

n數據類型說明符全局變量名;123456.5.2外部對象的連接屬性1016.6變量的存儲屬性1

02變量的生命期屬性生命期屬性反映程序運行時變量的存在狀態按照生命期屬性分類變量靜態變量動態變量存在周期與程序運行時間相同存在周期與定義它的代碼塊執行時間相同0

11

030

2變量的生命期屬性0

3全局變量是靜態變量0

4形式參數都是動態變量0

5局部變量有靜態變量、動態變量之分0

6s

t

a

t

i

c

a

u

t

o

/

r

e

g

i

s

t

e

r0

7靜態局部變量的存在周期與全局變量相同,作用域與局部0

8變量相同0

9靜態變量只能用常量初始化,未指定初值為0104int

f(int

a)?為了使局部變量的值在6.6.1變量的生命期屬性函數調用結束后不消失而保留原值,實現方法可以是:讓其占用的存儲單元不釋放,在下一次調用該函數時,該變量已有值,恰是上一次函數調用結束時的值。{

auto

intb=0;static

int

c=3;b+=1;

c+=1;return(a+b+c);}int

main(void){

int

a=2,k;for(k=0;kp<r3i;nkt+f+)("

%d",f(a));return

0;}1056.6.1變量的生命期屬性例1動態局部變量存儲特性int

z=0;程序運行結果:x=2

y=1z=1

z=1x=2

y=1z=1

z=1#include

<stdio.h>void

f(int

x){

int

y=0,i;printf("x=%d

y=%d

",++x,++y);for(i=p0r;in<t2f;(i"+z+=)%{d

",++z);}}int

main(void){

f(1);

putchar("\n");

f(1);

return

0;}1066.6.1變量的生命期屬性#include

<stdio.h>long

f

(

int

n

){if(n<=s1s)tatic

long

s;s=1;1

11......2!

3!1else10!s*=n;return

s;

}int

main(void){

int

i;

double

k=0;for(i=1;i<=10;i++)k+=1.0/f(i);printf("%lf

",

k);}01107變量的存儲器屬性02存儲器屬性反映程序運行期間變0304量獲得的存儲單元所在的存儲器按照存儲器屬性分類變量–內存變量–寄存器變量051086.4.5遞歸函數特點靜態變量(全局變量,靜態局部變量)都是內存變量動態變量(形式參數,動態局部變量)有內存變量和寄存器變量之分,由存儲類型說明符決定。用auto聲明的局部變量是內存變量;用register聲明的局部變量是寄存器變量;省略存儲類型說明符時系統默認為auto。寄存器變量的特殊性寄存器變量讀寫速度比內存變量快取地址運算符"&"不能用于寄存器變量1

00

190

26.8編譯預處理及預處理命令1

10在C程序的開發過程中,編譯源程序時編譯程序將對源程序文件作兩個階段的編譯預處理。第1階段:預處理程序預處理階段預處理程序掃描源程序,對其中的"預處理命令"做相應處理。預處理命令:文件包含命令宏定義命令條件編譯命令6.8.1預處理概念6.8.1預處理概念111第2階段:編譯程序預處理階段掃描源程序中的注釋,檢查是否符合書寫規則,若正確則將注釋替換為空格;例如:將以下代碼行:int

sum;/*

sum存放兩個數的和*/替換為:int

sum

;printf

(

"That"s

wonderful!"

)

;erful!"

)

;將以下2行代碼:查找源代碼中由續行符(反斜線后緊跟換行符)組成的物合并為1行代碼:printf

(

"That"s

wond\理行,把它們合并成一個邏輯行。1126.8.1預處理概念6.8.1預處理概念113(3)將源程序中用空白字符(空格,回車,TAB)作分隔符的多個字符串直接量連接為一個字符串直接量。將以下代碼行:printf

("A

string

is

a

sequence

of

characters"""sudrroouundbedlbye"q連u接ot為es:.");printf("A

string

is

a

sequence

of

characters

surrounded

by

double

quotes.");1146.8.2文件包含命令命令功能–預處理程序用filename文件中全部內容替代源程序中的預處理命令行#include"filename"使其成為源程序的一部分。命令格式#include"filename"或#include<filename>命令位置–允許出現在源程序中任何位置但必須是一行起始1

150

1文件包含命令0

2函數原型函數0

3符號常量:g

=

9

.

8

1

,

e

=

2

.

7

1

80

4#

i

n

c

l

u

d

e

<

f

i

l

e

2

.

c

>0

5BA0

6B0

7A0

81166.8.2

文件命令應用包:常含用含#i命ncl令ude命令將系統頭文件內容插入到源程序中。例如:#include<stdio.h>系統頭文件名主要內容標準I/O函數的原型、宏定義數學庫函數的原型及相關宏定義字符處理庫函數的原型stdio.hmath.hctype.hstring.hstdlib.hlimits.h字符串處理庫函數的原型常用的函數的原型、數據類型、變量定義定義與實現各種極限值時間、日期函數的原型time.h1176.8.2

文件包含命令#include

"c:\cpp\include\myfile.h"#include

"myfile.h"#include

<myfile.h>按指定路徑查找文件源程序文件所在目錄C編譯系統指定的include目錄1186.8.2文件包含命令優點復用缺點被包含的文件是源代碼,一個被包含文件被修改,所有相關文件須重新編譯包含順序(若file1包含file2,而file2中要用file3的內容)#include<file3.h>#include<file2.h>#include

命令,(不包含(不包含#include命令)使用file3.h的內容)..

..

....

..

..file1.cfile3.h..

....file2.h6.8.3宏定義命令119命令功能宏定義:用一個標識符(宏名)代表一個字符序列(宏主體)宏定義形式類對象宏定義#define

PI

3.14PI:宏名,3.14:宏體類函數宏定義類對象宏定義#include<stdio.h>120#define

price

30/*price代表30

*/int

main(void){預處理之前int

number,money;number=10;money=price*number;printf(“price

%d

a

book

,%d

books

cost\$%d!\n”,

price,

number,

money);return

0;}類對象宏定義121#include

<stdio.h>int

main(void){預處理之后int

number,money;number=10;money=30*number;printf(“price

%d

a

book

,%d

books\cost

$%d.\n”,30,number,money);return

0;6.8.3宏定義命令122預處理程序允許在一個類對象宏定義命令行中使用先前已定義過的宏名#define

溫馨提示

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

評論

0/150

提交評論