在結(jié)構(gòu)化程序設(shè)計中函數(shù)是將任務進行模塊劃分的基本單位
《在結(jié)構(gòu)化程序設(shè)計中函數(shù)是將任務進行模塊劃分的基本單位》由會員分享,可在線閱讀,更多相關(guān)《在結(jié)構(gòu)化程序設(shè)計中函數(shù)是將任務進行模塊劃分的基本單位(109頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、 在結(jié)構(gòu)化程序設(shè)計中,函數(shù)是將任務進行模塊劃分的基在結(jié)構(gòu)化程序設(shè)計中,函數(shù)是將任務進行模塊劃分的基本單位。一個函數(shù)實現(xiàn)一項功能。本單位。一個函數(shù)實現(xiàn)一項功能。 在面向?qū)ο笤诿嫦驅(qū)ο蟪绦蛟O(shè)計中,程序設(shè)計中,函數(shù)是對數(shù)據(jù)的一項操作,也函數(shù)是對數(shù)據(jù)的一項操作,也是實現(xiàn)一項功能。是實現(xiàn)一項功能。第三章第三章 函數(shù)函數(shù) 要掌握函數(shù)的使用,必須理解函數(shù)調(diào)用時的內(nèi)部實現(xiàn)機要掌握函數(shù)的使用,必須理解函數(shù)調(diào)用時的內(nèi)部實現(xiàn)機制,以及與此相關(guān)的內(nèi)存分配機制、變量生命期和作用域。制,以及與此相關(guān)的內(nèi)存分配機制、變量生命期和作用域。 本章還將介紹關(guān)于函數(shù)重載的概念,介紹遞歸算法本章還將介紹關(guān)于函數(shù)重載的概念,介紹遞歸算
2、法、內(nèi)聯(lián)函數(shù)、默認參數(shù)函數(shù)以及多文件組織、編譯預處、內(nèi)聯(lián)函數(shù)、默認參數(shù)函數(shù)以及多文件組織、編譯預處理、工程文件的概念和運行庫函數(shù)。理、工程文件的概念和運行庫函數(shù)。 練習:編寫程序,輸入練習:編寫程序,輸入x x,根據(jù)下面,根據(jù)下面y y和和x x的關(guān)的關(guān)系,計算系,計算y y值并輸出值并輸出3x-11 (x10)x (x1)2x-1 (1xx; cinx; if(x1) y=x; if(x1) y=x; else if(1=x10) y=2 else if(1=x10) y=2* *x-1;x-1; else y=3 else y=3* *x-11;x-11; couty; coutx; ci
3、nx; if(x1) y=x; if(x1) y=x; else if(1=x&x10) y=2 else if(1=x&x10) y=2* *x-1;x-1; else y=3 else y=3* *x-11;x-11; couty; coutx; cinx; if(x1) y=x; if(x1) y=x; else if(1 else if(1x10) y=2x10) y=2* *x-1;x-1; else y=3 else y=3* *x-11;x-11; couty; coutx; cinx; x=10?y=3x-11:y=2x-1 x=10?y=3x-11:y=2x-1 couty;
4、 coutx; cinx; if(x1) y=x; if(x1) y=x; else if(x10) y=2 else if(x10) y=2* *x-1;x-1; else y=3 else y=3* *x-11;x-11; couty; couty; 第三章第三章 函數(shù)函數(shù) 3.1 函數(shù)的定義與調(diào)用函數(shù)的定義與調(diào)用 3. 5 作用域與標識符的可見性作用域與標識符的可見性 3.4 函數(shù)調(diào)用機制函數(shù)調(diào)用機制 3.3 全局變量和局部變量全局變量和局部變量 3.2 函數(shù)的參數(shù)傳遞函數(shù)的參數(shù)傳遞,返回值及函數(shù)聲明返回值及函數(shù)聲明 3.10 編譯預處理編譯預處理 3.9 頭文件與多文件結(jié)構(gòu)頭文件與多文
5、件結(jié)構(gòu) 3.6 存儲類型與標識符的生命期存儲類型與標識符的生命期 3.8 函數(shù)的一些高級議題函數(shù)的一些高級議題 3.7 函數(shù)的遞歸調(diào)用函數(shù)的遞歸調(diào)用 3.1 函數(shù)的定義與調(diào)用函數(shù)的定義與調(diào)用3.1.1 函數(shù)概述函數(shù)概述3.1.2 函數(shù)的定義函數(shù)的定義3.1.3 函數(shù)的調(diào)用函數(shù)的調(diào)用 3.1.1 函數(shù)概述函數(shù)概述函數(shù)是函數(shù)是C+C+程序的基本組成模塊。程序的基本組成模塊。通過函數(shù),可以把一個復雜任務分解成為若干通過函數(shù),可以把一個復雜任務分解成為若干個易于解決的小任務。充分體現(xiàn)逐步細化的設(shè)計思個易于解決的小任務。充分體現(xiàn)逐步細化的設(shè)計思想。想。組成組成C+C+程序的若干函數(shù)中,有一個稱為程序的若
6、干函數(shù)中,有一個稱為main()main()(Winmain()Winmain())函數(shù),是程序執(zhí)行的入口,它可以)函數(shù),是程序執(zhí)行的入口,它可以調(diào)調(diào)用其他函數(shù),但不可以被調(diào)用用其他函數(shù),但不可以被調(diào)用。而其他一般。而其他一般函數(shù)既可函數(shù)既可以調(diào)用也可以被調(diào)用。以調(diào)用也可以被調(diào)用。函數(shù)概念的引入:函數(shù)概念的引入:入口函數(shù):入口函數(shù):3.1.1 函數(shù)概述函數(shù)概述main ( )fun2( )fun1( )fun3( )funa( )funb( )func( )圖圖3.1 3.1 函數(shù)調(diào)用層次關(guān)系函數(shù)調(diào)用層次關(guān)系3.1.1 函數(shù)概述函數(shù)概述3.1.1結(jié)束結(jié)束庫函數(shù)和自定義函數(shù):庫函數(shù)和自定義函數(shù):
7、 庫函數(shù)庫函數(shù)或或標準函數(shù)標準函數(shù),是由編譯系統(tǒng)預定義的,是由編譯系統(tǒng)預定義的,如一些常用的數(shù)學計算函數(shù)、字符串處理函數(shù)、圖如一些常用的數(shù)學計算函數(shù)、字符串處理函數(shù)、圖形處理函數(shù)、標準輸入輸出函數(shù)等。形處理函數(shù)、標準輸入輸出函數(shù)等。 庫函數(shù)都按功能分類,集中說明在不同的頭文庫函數(shù)都按功能分類,集中說明在不同的頭文件中件中。用戶只需在自己的程序中包含某個頭文件,。用戶只需在自己的程序中包含某個頭文件,就可直接使用該文件中定義的函數(shù)。就可直接使用該文件中定義的函數(shù)。 用戶根據(jù)需要將某個具有相對獨立功能的程序用戶根據(jù)需要將某個具有相對獨立功能的程序定義為函數(shù),稱定義為函數(shù),稱自定義函數(shù)自定義函數(shù)。四
8、個要素:四個要素:返回值類型,函數(shù)名,參數(shù)列表和函數(shù)體返回值類型,函數(shù)名,參數(shù)列表和函數(shù)體3.1.2 函數(shù)的定義函數(shù)的定義無參函數(shù)定義格式為:無參函數(shù)定義格式為:數(shù)據(jù)類型數(shù)據(jù)類型函數(shù)名函數(shù)名( (voidvoid)函數(shù)體函數(shù)體 說明:說明: 數(shù)據(jù)類型指函數(shù)數(shù)據(jù)類型指函數(shù)返回值類型返回值類型,可以是任一種數(shù)據(jù)類型。,可以是任一種數(shù)據(jù)類型。沒有返回值應將返回值類型定義為沒有返回值應將返回值類型定義為voidvoid。 函數(shù)名函數(shù)名采用合法標識符表示。采用合法標識符表示。 對無參函數(shù),參數(shù)括號中的對無參函數(shù),參數(shù)括號中的voidvoid通常省略,但括號不通常省略,但括號不能省略。能省略。 函數(shù)體由一
9、系列語句組成。函數(shù)體由一系列語句組成。函數(shù)體函數(shù)體可以為空,稱為空可以為空,稱為空函數(shù)。函數(shù)。 3.1.2 函數(shù)的定義函數(shù)的定義例例: 打印一個表頭打印一個表頭void TableHead ( ) cout*endl;cout* example *endl;cout*=b?a:b; return(x); 有參函數(shù)的參數(shù)表中列出所有有參函數(shù)的參數(shù)表中列出所有形式參數(shù)形式參數(shù)的類型和參數(shù)名的類型和參數(shù)名稱。各參數(shù)即使類型相同也必須分別加以說明。稱。各參數(shù)即使類型相同也必須分別加以說明。 形式參數(shù)簡稱形參,形式參數(shù)簡稱形參,只能是變量名只能是變量名,不允許是常量或表,不允許是常量或表達式。達式。 W
10、hy?找錯誤int f()string s;.return s;f2(int i).int f(int v1,int v2).double square(double x)return x*x;問題:問題:定義函數(shù)時究竟哪些變量應當作為函數(shù)的參數(shù)?哪些定義函數(shù)時究竟哪些變量應當作為函數(shù)的參數(shù)?哪些應當定義在函數(shù)體內(nèi)?應當定義在函數(shù)體內(nèi)?原則原則:函數(shù)在使用時被看成函數(shù)在使用時被看成 “ “黑匣子黑匣子”,除了輸入輸出外,除了輸入輸出外,其他部分可不必關(guān)心其他部分可不必關(guān)心。從函數(shù)的定義看出,函數(shù)頭正是用來。從函數(shù)的定義看出,函數(shù)頭正是用來反映函數(shù)的功能和使用接口,它所定義的是反映函數(shù)的功能和使
11、用接口,它所定義的是“做什么做什么”。即。即明確了明確了“黑匣子黑匣子”的輸入輸出部分,的輸入輸出部分,輸出就是函數(shù)的返回值,輸出就是函數(shù)的返回值,輸入就是參數(shù)輸入就是參數(shù)。因此,只有那些功能上起自變量作用的變量。因此,只有那些功能上起自變量作用的變量才必須作為參數(shù)定義在參數(shù)表中;函數(shù)體中具體描述才必須作為參數(shù)定義在參數(shù)表中;函數(shù)體中具體描述“如何如何做做”,因此除參數(shù)之外的為實現(xiàn)算法所需用的變量應當定義,因此除參數(shù)之外的為實現(xiàn)算法所需用的變量應當定義在函數(shù)體內(nèi)。在函數(shù)體內(nèi)。 C+C+中不允許函數(shù)的嵌套定義,即在一個函數(shù)中定義另一中不允許函數(shù)的嵌套定義,即在一個函數(shù)中定義另一個函數(shù)。個函數(shù)。提
12、示提示3.1.3 函數(shù)的調(diào)用函數(shù)的調(diào)用函數(shù)調(diào)用:函數(shù)調(diào)用: 所謂函數(shù)調(diào)用,就是使程序轉(zhuǎn)去執(zhí)行函數(shù)體。所謂函數(shù)調(diào)用,就是使程序轉(zhuǎn)去執(zhí)行函數(shù)體。 在在C+C+中,除了主函數(shù)外,其他任何函數(shù)都不能單獨作中,除了主函數(shù)外,其他任何函數(shù)都不能單獨作為程序運行。任何函數(shù)功能的實現(xiàn)都是通過被主函數(shù)直接或為程序運行。任何函數(shù)功能的實現(xiàn)都是通過被主函數(shù)直接或間接調(diào)用進行的。間接調(diào)用進行的。 無參函數(shù)的調(diào)用格式:無參函數(shù)的調(diào)用格式: 函數(shù)名函數(shù)名( )( ) 有參函數(shù)的調(diào)用格式:有參函數(shù)的調(diào)用格式: 函數(shù)名函數(shù)名( (實際參數(shù)表實際參數(shù)表) )其中實際參數(shù)簡稱其中實際參數(shù)簡稱實參實參,用來將實際參數(shù)的值傳遞給形參
13、,用來將實際參數(shù)的值傳遞給形參,因此因此可以是常量、具有值的變量或表達式可以是常量、具有值的變量或表達式。【例【例3.1】 輸入兩個實數(shù),輸出其中較大的數(shù)輸入兩個實數(shù),輸出其中較大的數(shù) 函數(shù)的調(diào)用規(guī)則1、調(diào)用函數(shù)時,函數(shù)名必須與調(diào)用處的函數(shù)名完全一致。2、實參的個數(shù)必須與形參的個數(shù)一致。3、函數(shù)必須先聲明或定義,后調(diào)用。4、函數(shù)可以直接或間接地自己調(diào)用自己,稱為遞歸調(diào)用。int main() int add(int x, int y); int a=100,b=200,c ; c =add(a,b); .int add (int x, int y ) int z ; z=x+y; return
14、(z);錯誤:c=ad(a,b);c=add(a);int add(int , int );3.2 函數(shù)的參數(shù)傳遞、返回值及函數(shù)的參數(shù)傳遞、返回值及函數(shù)聲明函數(shù)聲明 321 函數(shù)的參數(shù)傳遞及傳值調(diào)用函數(shù)的參數(shù)傳遞及傳值調(diào)用 323 函數(shù)聲明函數(shù)聲明322 函數(shù)返回值函數(shù)返回值 參數(shù)傳遞:參數(shù)傳遞: 函數(shù)調(diào)用首先要進行參數(shù)傳遞,參數(shù)傳遞的方向是函數(shù)調(diào)用首先要進行參數(shù)傳遞,參數(shù)傳遞的方向是由實由實參傳遞給形參參傳遞給形參。 傳遞過程是,傳遞過程是,先計算實參表達式的值,再將該值傳遞給先計算實參表達式的值,再將該值傳遞給對應的形參變量對應的形參變量。一般情況下,。一般情況下,實參和形參的個數(shù)和排列順
15、實參和形參的個數(shù)和排列順序應一一對應,并且對應參數(shù)應類型匹配序應一一對應,并且對應參數(shù)應類型匹配(賦值兼容)(賦值兼容), ,即即實參的類型可以轉(zhuǎn)化為形參類型。而對應參數(shù)的參數(shù)名則不實參的類型可以轉(zhuǎn)化為形參類型。而對應參數(shù)的參數(shù)名則不要求相同。要求相同。 3.2.1 函數(shù)的參數(shù)傳遞及傳值調(diào)用函數(shù)的參數(shù)傳遞及傳值調(diào)用 傳值調(diào)用和引用調(diào)用:傳值調(diào)用和引用調(diào)用:按照參數(shù)形式的不同,按照參數(shù)形式的不同,C+有兩種調(diào)用方式:有兩種調(diào)用方式:傳值調(diào)用傳值調(diào)用和和引引用調(diào)用用調(diào)用。傳值調(diào)用傳遞的是實參的值,本章介紹傳值調(diào)用。傳值調(diào)用傳遞的是實參的值,本章介紹傳值調(diào)用。在調(diào)用函數(shù)時,一般在主調(diào)函數(shù)和被調(diào)用函數(shù)
16、之間有 信息傳遞 這是由函數(shù)中的參數(shù)參數(shù)來完成的。調(diào)用函數(shù)和被調(diào)用函數(shù)之間的參數(shù)傳遞實際參數(shù)實際參數(shù) 形式參數(shù)形式參數(shù)主調(diào)用函數(shù)中的參數(shù)被調(diào)用函數(shù)中的參數(shù)(實參實參)(形參形參)int main() int a=5,b=10, c ; c=max(a,b); printf(“c=%dn”, c); return 0;int max(int x, int y) int t; if (xy) t=x; else t=y; return(t); yxa5b10510ct101010int main() int a=5,b=10, c ; c=max(a,b); printf(“c=%dn”, c);
17、 return 0; int max(int x, int y) int t; if (xy) t=x; else t=y; return(t); 信息傳遞原則:信息傳遞原則:實參到形參實參到形參單向值傳遞單向值傳遞特點:實參與形參各占用不同的內(nèi)存單元 3.2.1 函數(shù)的參數(shù)傳遞及傳值調(diào)用函數(shù)的參數(shù)傳遞及傳值調(diào)用 傳值調(diào)用:傳值調(diào)用:將實參的值復制給形參,在函數(shù)中參加運算的將實參的值復制給形參,在函數(shù)中參加運算的是形參,而實參不會發(fā)生任何改變。傳值調(diào)用是形參,而實參不會發(fā)生任何改變。傳值調(diào)用起了一種隔離作用。起了一種隔離作用?!纠纠?.2】 實參和形參對應關(guān)系的示例。實參和形參對應關(guān)系的示例
18、。注意:注意:【例【例1.3】中調(diào)用函數(shù)】中調(diào)用函數(shù)strcpy(s3, s2),卻實現(xiàn)了字符數(shù),卻實現(xiàn)了字符數(shù)組組s2的內(nèi)容復制到字符數(shù)組的內(nèi)容復制到字符數(shù)組s3中。這是因為數(shù)組名實際中。這是因為數(shù)組名實際上代表存儲數(shù)組的內(nèi)存的首地址,復制給形參的是實參數(shù)上代表存儲數(shù)組的內(nèi)存的首地址,復制給形參的是實參數(shù)組的首地址,結(jié)果參加運算的是實參數(shù)組。數(shù)組作為參數(shù)組的首地址,結(jié)果參加運算的是實參數(shù)組。數(shù)組作為參數(shù),定義時形參用數(shù)組名加一對方括號,調(diào)用時實參只用數(shù),定義時形參用數(shù)組名加一對方括號,調(diào)用時實參只用數(shù)組名組名 100aFFC2200bFFC4int add (int x, int y) in
19、t z ; z=(+x)+(+y) ; return(z); int main() int a=100,b=200,c ; c =add(a,b); coutcendl; return 0; 100 xFFA2200yFFA4101201302z1094302cFFC6 當形參值在函 數(shù)中發(fā)生變化時, 且不影響調(diào)用它的 實參值的變化。 用途 采用這種數(shù)據(jù)復制的參數(shù)傳遞方式,每次每個參數(shù)只能傳遞一個數(shù)據(jù)。缺點add (a , b) ;int add ( x, y ) A) 11 B) 20 C) 21 D) 31請寫出下列程序的運行結(jié)果 main() int x=6,y=7,z=8,r ; r=
20、f (x-,y+,x+y),z-); coutr=ry) t=x; else t=y; return(t); 下面是一個使用結(jié)構(gòu)化程序設(shè)計思想開發(fā)的企業(yè)管理下面是一個使用結(jié)構(gòu)化程序設(shè)計思想開發(fā)的企業(yè)管理報表程序的框架。它使用了報表程序的框架。它使用了函數(shù)聲明函數(shù)聲明。void menu_print();void account_report();void engineering_report();void marketing_report();int main() int choice; do menu_print();cinchoice; while(choice=4); switch(ch
21、oice) case 1: account_report(); break; case 2: engineering_report(); break; case 3: marketing_report(); break; return 0;void menu_print() cout”系統(tǒng)功能:系統(tǒng)功能:”endl; cout”1 財務報表財務報表”endl; cout”2 工程報表工程報表”endl; cout”3 市場報表市場報表”endl; cout”選擇業(yè)務序號:選擇業(yè)務序號:”; void account_report() /生成財務報表生成財務報表void engineering_
22、report() /生成工程報表生成工程報表 void marketing_report() /生成市場報表;生成市場報表;3.2.3 函數(shù)聲明函數(shù)聲明【例【例3.4】 輸出所有滿足下列條件的正整數(shù)輸出所有滿足下列條件的正整數(shù)m:10m1000且且m、m2、m3均為回文數(shù)。均為回文數(shù)。分析:分析:回文指左右對稱的序列。如回文指左右對稱的序列。如121、353等就是回等就是回文數(shù)。判斷整數(shù)是否回文數(shù)用函數(shù)實現(xiàn),其思想是將文數(shù)。判斷整數(shù)是否回文數(shù)用函數(shù)實現(xiàn),其思想是將該數(shù)各位拆開后反向組成新的整數(shù),如果該整數(shù)與原該數(shù)各位拆開后反向組成新的整數(shù),如果該整數(shù)與原數(shù)相等則為回文數(shù)。數(shù)相等則為回文數(shù)。m
23、m*m m*m*m11 121 1331101 10201 1030301111 12321 1367631 運行結(jié)果:運行結(jié)果:3.3 全局變量和局部變量全局變量和局部變量 3.3.1 變量的存儲機制與變量的存儲機制與C+的內(nèi)存布局的內(nèi)存布局自由存儲區(qū)自由存儲區(qū) ( (動態(tài)數(shù)據(jù)動態(tài)數(shù)據(jù)) )棧區(qū)(函數(shù)局部數(shù)據(jù))棧區(qū)(函數(shù)局部數(shù)據(jù))(main()main()函數(shù)局部數(shù)據(jù))函數(shù)局部數(shù)據(jù))全局數(shù)據(jù)區(qū)全局數(shù)據(jù)區(qū)( (全局、靜態(tài)全局、靜態(tài)) )代碼區(qū)(程序代碼)代碼區(qū)(程序代碼) 操作系統(tǒng)為一個操作系統(tǒng)為一個C+C+程序的運行所分配的內(nèi)程序的運行所分配的內(nèi)存分為四個區(qū)域,如圖存分為四個區(qū)域,如圖3.3
24、3.3 所示:所示:存儲區(qū)域說明:存儲區(qū)域說明:(1)代碼區(qū)()代碼區(qū)(Code area):存放程序代碼,即程序):存放程序代碼,即程序中各個函數(shù)的代碼塊;中各個函數(shù)的代碼塊;(2)全局數(shù)據(jù)區(qū)()全局數(shù)據(jù)區(qū)(Data area):存放全局數(shù)據(jù)和靜):存放全局數(shù)據(jù)和靜態(tài)數(shù)據(jù);態(tài)數(shù)據(jù);分配該區(qū)時內(nèi)存全部清零分配該區(qū)時內(nèi)存全部清零,結(jié)果變量的所有字,結(jié)果變量的所有字節(jié)自動初始化為零。節(jié)自動初始化為零。(3)棧區(qū)()棧區(qū)(Stack area):存放局部變量,如函數(shù)中):存放局部變量,如函數(shù)中的變量等;的變量等;分配棧區(qū)時不處理內(nèi)存分配棧區(qū)時不處理內(nèi)存,即變量取隨機值。,即變量取隨機值。(4)自由存
25、儲區(qū)(自由存儲區(qū)(Free store area):):存放與指針相存放與指針相關(guān)的動態(tài)數(shù)據(jù)。關(guān)的動態(tài)數(shù)據(jù)。分配分配自由存儲自由存儲區(qū)時不處理內(nèi)存區(qū)時不處理內(nèi)存。參見第。參見第七章。七章。3.3.1 變量的存儲機制與變量的存儲機制與C+的內(nèi)存布局的內(nèi)存布局 3.3.2 全局變量全局變量 在所有函數(shù)之外定義的變量稱為在所有函數(shù)之外定義的變量稱為全局變量全局變量。全局變量在全局變量在編譯時編譯時建立在全局數(shù)據(jù)區(qū),在未給建立在全局數(shù)據(jù)區(qū),在未給出初始化值時系統(tǒng)自動出初始化值時系統(tǒng)自動初始化為全初始化為全0。全局變量可定義在程序開頭,也可定義在中間全局變量可定義在程序開頭,也可定義在中間位置,該全局變
26、量位置,該全局變量在定義處之后在定義處之后的任何位置都是可的任何位置都是可以訪問的,稱為可見的。以訪問的,稱為可見的?!纠纠?.5】 多個函數(shù)使用全局變量的例子。多個函數(shù)使用全局變量的例子。全局變量引入:全局變量引入:3.3.3 局部變量局部變量 定義在函數(shù)內(nèi)或塊內(nèi)的變量稱為定義在函數(shù)內(nèi)或塊內(nèi)的變量稱為局部變量局部變量。程序中使用的絕大多數(shù)變量都是局部變量。程序中使用的絕大多數(shù)變量都是局部變量。局部變量在局部變量在程序運行程序運行到它所在的塊時建立在棧中,到它所在的塊時建立在棧中,該塊執(zhí)行完畢局部變量占有的空間即被釋放。該塊執(zhí)行完畢局部變量占有的空間即被釋放。局部變量在定義時可加修飾詞局部變
27、量在定義時可加修飾詞auto,但通常省略。但通常省略。局部變量在定義時若未初始化,其值為隨機數(shù)。局部變量在定義時若未初始化,其值為隨機數(shù)。局部變量引入:局部變量引入:【例【例3.6】 使用局部變量的例子。使用局部變量的例子。思考:如果定義思考:如果定義一個對象一個對象/變量為變量為全局模式還是局全局模式還是局部模式?部模式? 1、主函數(shù)中定義的變量也只用在主函數(shù)中有效;關(guān)于局部變量使用的幾點說明 2、不同函數(shù)中可以使用相同的變量名,且它們代 表不同的存儲單元,互不干擾; 3、形式參數(shù)也是局部變量。其它函數(shù)是不能調(diào)用 該形參的; 4、在一個函數(shù)內(nèi)部,可以在復合語句中定義變量 ,這些變量只能在本復
28、合語句中有效。3.4 函數(shù)調(diào)用機制函數(shù)調(diào)用機制 局部變量占用的內(nèi)存是在程序執(zhí)行過程中局部變量占用的內(nèi)存是在程序執(zhí)行過程中“動態(tài)動態(tài)”地建立地建立和釋放的。這種和釋放的。這種“動態(tài)動態(tài)”是通過棧由系統(tǒng)自動管理進行的。是通過棧由系統(tǒng)自動管理進行的。(1)建立??臻g;)建立??臻g;(6)恢復現(xiàn)場:取主調(diào)函數(shù)運行狀態(tài)及返回地址,釋放棧空間;)恢復現(xiàn)場:取主調(diào)函數(shù)運行狀態(tài)及返回地址,釋放??臻g;(7)繼續(xù)主調(diào)函數(shù)后續(xù)語句。)繼續(xù)主調(diào)函數(shù)后續(xù)語句。(5)釋放被調(diào)函數(shù)中局部變量占用的??臻g;)釋放被調(diào)函數(shù)中局部變量占用的棧空間;(4)執(zhí)行被調(diào)函數(shù)函數(shù)體;)執(zhí)行被調(diào)函數(shù)函數(shù)體;(3)為被調(diào)函數(shù)中的局部變量分配
29、空間,完成參數(shù)傳遞;)為被調(diào)函數(shù)中的局部變量分配空間,完成參數(shù)傳遞;(2)保護現(xiàn)場:主調(diào)函數(shù)運行狀態(tài)和返回地址入棧;)保護現(xiàn)場:主調(diào)函數(shù)運行狀態(tài)和返回地址入棧;調(diào)用過程:調(diào)用過程:3.4 函數(shù)調(diào)用機制函數(shù)調(diào)用機制 void fun1(int, int);void fun2(float);int main() int x=1;y=2; fun1(x, y); return 0;void fun1(int a,int b) float x=3; fun2(x);void fun2(float y) int x; x棧頂棧頂棧底棧底y3fun2()fun1()運行狀態(tài)及返回地址運行狀態(tài)及返回地址x3
30、b2a1fun1()main()運行狀態(tài)及返回地址運行狀態(tài)及返回地址y2x1main()操作系統(tǒng)運行狀態(tài)及返回地址操作系統(tǒng)運行狀態(tài)及返回地址此圖例說明在程序執(zhí)行過程中怎樣通過棧此圖例說明在程序執(zhí)行過程中怎樣通過?!皠討B(tài)動態(tài)”地建立和地建立和釋放局部變量占用的內(nèi)存的釋放局部變量占用的內(nèi)存的地址地址.0XFE8020X5984D0XFE154 3.5 作用域與標識符的可見性作用域與標識符的可見性3 文件作用域文件作用域 2 函數(shù)聲明作用域函數(shù)聲明作用域 作用域:作用域:指標識符能夠被使用的范圍。只有在作指標識符能夠被使用的范圍。只有在作用域內(nèi)標識符才可以被訪問(稱為可見)。用域內(nèi)標識符才可以被訪問
31、(稱為可見)。本節(jié)重點討論本節(jié)重點討論局部域局部域和文件域(全局域),其中和文件域(全局域),其中局部域包括局部域包括塊域塊域和和函數(shù)聲明域函數(shù)聲明域。任何。任何標識符標識符作用域的作用域的起始點均為起始點均為標識符說明標識符說明處。處。下面分別介紹下面分別介紹:1 塊作用域塊作用域 函數(shù)中定義的標識符,包括形參和函數(shù)體中定義函數(shù)中定義的標識符,包括形參和函數(shù)體中定義的局部變量,作用域都在該函數(shù)內(nèi),也稱作的局部變量,作用域都在該函數(shù)內(nèi),也稱作函數(shù)域函數(shù)域。1. 塊域塊域塊塊指一對大括號括起來的程序段。塊中定義的標指一對大括號括起來的程序段。塊中定義的標識符,作用域在塊內(nèi)。識符,作用域在塊內(nèi)。復
32、合語句是一個塊。復合語句是一個塊。函數(shù)也是一個塊。函數(shù)也是一個塊。復合語句中定義的標識符,復合語句中定義的標識符,作用域僅在該復合語句中。作用域僅在該復合語句中?!纠纠?.7】 輸入兩數(shù),按從大到小的順序保存。輸入兩數(shù),按從大到小的順序保存。塊的引入:塊的引入:1. 塊域塊域由由VC+平臺運行,結(jié)果如下:平臺運行,結(jié)果如下:輸入兩整數(shù):輸入兩整數(shù):3 5調(diào)用前:實參調(diào)用前:實參a=3,b=5調(diào)用中調(diào)用中交換前:形參交換前:形參a=3,b=5交換后:形參交換后:形參a=5,b=3調(diào)用后:實參調(diào)用后:實參a=3,b=5 交換失敗交換失敗局部變量具有局部作用域使得程序在不同塊中可以局部變量具有局部
33、作用域使得程序在不同塊中可以使用同名變量。這些同名變量各自在自己的作用域使用同名變量。這些同名變量各自在自己的作用域中可見,在其它地方不可見。中可見,在其它地方不可見。【例【例3.8】設(shè)計函數(shù)完成兩數(shù)交換,用主函數(shù)進行測試。設(shè)計函數(shù)完成兩數(shù)交換,用主函數(shù)進行測試。1. 塊域塊域 對于塊中對于塊中嵌套嵌套其它塊的情況,如果嵌套塊中有同其它塊的情況,如果嵌套塊中有同名局部變量,服從局部優(yōu)先原則,即在內(nèi)層塊中名局部變量,服從局部優(yōu)先原則,即在內(nèi)層塊中屏屏蔽蔽外層塊中的同名變量,換句話說,內(nèi)層塊中局部外層塊中的同名變量,換句話說,內(nèi)層塊中局部變量的作用域為內(nèi)層塊;外層塊中局部變量的作用變量的作用域為內(nèi)
34、層塊;外層塊中局部變量的作用域為外層除去包含同名變量的內(nèi)層塊部分。域為外層除去包含同名變量的內(nèi)層塊部分。如果塊內(nèi)定義的局部變量與全局變量同名,塊內(nèi)仍如果塊內(nèi)定義的局部變量與全局變量同名,塊內(nèi)仍然局部變量優(yōu)先,但與塊作用域不同的是,在塊內(nèi)然局部變量優(yōu)先,但與塊作用域不同的是,在塊內(nèi)可以通過域運算符可以通過域運算符“:”訪問同名的全局變量。訪問同名的全局變量?!纠纠?.9】 顯示同名變量可見性。顯示同名變量可見性。2函數(shù)聲明作用域函數(shù)聲明作用域 函數(shù)聲明不是定義函數(shù),在作函函數(shù)聲明不是定義函數(shù),在作函數(shù)聲明時,其中的形參作用域只在數(shù)聲明時,其中的形參作用域只在聲明中,即聲明中,即作用域結(jié)束于右括
35、號作用域結(jié)束于右括號。正是由于形參不能被程序的其他地正是由于形參不能被程序的其他地方引用,所以通常只要聲明形參個方引用,所以通常只要聲明形參個數(shù)和類型,數(shù)和類型,形參名可省略形參名可省略。3 3 文件作用域文件作用域 文件作用域文件作用域也稱全局作用域。定義在所有函數(shù)之外的也稱全局作用域。定義在所有函數(shù)之外的標識符,具有文件作用域,作用域為從定義處到整個標識符,具有文件作用域,作用域為從定義處到整個源文件結(jié)束。文件中定義的全局變量和函數(shù)都具有文源文件結(jié)束。文件中定義的全局變量和函數(shù)都具有文件作用域。件作用域。如果某個文件中說明了具有文件作用域的標識符,該如果某個文件中說明了具有文件作用域的標識
36、符,該文件又被另一個文件包含,則該標識符的作用域延伸文件又被另一個文件包含,則該標識符的作用域延伸到新的文件中。如到新的文件中。如cincin和和coutcout是在頭文件是在頭文件iostreamiostream中說明中說明的具有文件作用域的標識符,它們的作用域也延伸到的具有文件作用域的標識符,它們的作用域也延伸到嵌入嵌入iostreamiostream的文件中。的文件中。存儲類型(存儲類型(storage class)決定標識符的存儲)決定標識符的存儲區(qū)域,即編譯系統(tǒng)在不同區(qū)域為不同存儲類型的標區(qū)域,即編譯系統(tǒng)在不同區(qū)域為不同存儲類型的標識符分配空間。由于存儲區(qū)域不同,標識符的生命識符分配
37、空間。由于存儲區(qū)域不同,標識符的生命期也不同。所謂生命期,指的是標識符從獲得空間期也不同。所謂生命期,指的是標識符從獲得空間到空間釋放之間的期間,標識符只有在生存期中、到空間釋放之間的期間,標識符只有在生存期中、并且在其自己的作用域中才能被訪問。并且在其自己的作用域中才能被訪問。3.6 存儲類型與標識符的生命期存儲類型與標識符的生命期 自動變量為用自動變量為用auto說明的變量,通常說明的變量,通常auto缺省。局部變量都是自缺省。局部變量都是自動變量,生命期開始于塊的執(zhí)行,結(jié)束于塊的結(jié)束,其原動變量,生命期開始于塊的執(zhí)行,結(jié)束于塊的結(jié)束,其原因是自動變量的空間分配在棧中,塊開始執(zhí)行時系統(tǒng)自動
38、因是自動變量的空間分配在棧中,塊開始執(zhí)行時系統(tǒng)自動分配空間,塊執(zhí)行結(jié)束時系統(tǒng)自動釋放空間。故自動變量分配空間,塊執(zhí)行結(jié)束時系統(tǒng)自動釋放空間。故自動變量的生命期和作用域是一致的。的生命期和作用域是一致的。3.6.1 存儲類型存儲類型 為提高程序運行效率,可以將某些變量保存在寄存器中,即用為提高程序運行效率,可以將某些變量保存在寄存器中,即用register說明為寄存器變量,說明為寄存器變量,但不提倡使用但不提倡使用。C+中關(guān)于存儲類型的說明符(中關(guān)于存儲類型的說明符(storage class specifier)有四)有四個:個:auto、register、static和和extern。其中用
39、。其中用auto和和register修修飾的稱為自動存儲類型,用飾的稱為自動存儲類型,用static修飾的稱為靜態(tài)存儲類型,修飾的稱為靜態(tài)存儲類型,用用extern修飾的稱為外部存儲類型。修飾的稱為外部存儲類型。1 1 自動存儲類型自動存儲類型static說明的變量稱為靜態(tài)變量。根據(jù)定義的位置不同,還說明的變量稱為靜態(tài)變量。根據(jù)定義的位置不同,還分為局部靜態(tài)變量和全局靜態(tài)變量,也稱內(nèi)部靜態(tài)變量和外部分為局部靜態(tài)變量和全局靜態(tài)變量,也稱內(nèi)部靜態(tài)變量和外部靜態(tài)變量。靜態(tài)變量均存儲在全局數(shù)據(jù)區(qū),如果程序未顯式給靜態(tài)變量。靜態(tài)變量均存儲在全局數(shù)據(jù)區(qū),如果程序未顯式給出初始化值,系統(tǒng)自動初始化為全出初始
40、化值,系統(tǒng)自動初始化為全0,且初始化只進行一次;靜,且初始化只進行一次;靜態(tài)變量占有的空間要到整個程序執(zhí)行結(jié)束才釋放,故靜態(tài)變量態(tài)變量占有的空間要到整個程序執(zhí)行結(jié)束才釋放,故靜態(tài)變量具有全局生命期。具有全局生命期。3.6.1 存儲類型存儲類型局部靜態(tài)變量是定義在塊中的靜態(tài)變量,當塊第一次被執(zhí)行時,局部靜態(tài)變量是定義在塊中的靜態(tài)變量,當塊第一次被執(zhí)行時,編譯系統(tǒng)在全局數(shù)據(jù)區(qū)為其開辟空間并保存數(shù)據(jù),該空間一直編譯系統(tǒng)在全局數(shù)據(jù)區(qū)為其開辟空間并保存數(shù)據(jù),該空間一直到整個程序結(jié)束才釋放。局部靜態(tài)變量具有局部作用域,但卻到整個程序結(jié)束才釋放。局部靜態(tài)變量具有局部作用域,但卻具有全局生命期。具有全局生命期
41、?!纠纠?.10】 自動變量與局部靜態(tài)變量的區(qū)別自動變量與局部靜態(tài)變量的區(qū)別 int f( int a) auto int b=0; static int c=3; b=b+1;c=c+1; return(a+b+c); int main() int a=2, i ; for(i=0; i 3; i +) cout f(a)endl; 0b3c1舉舉例例2a2a4701580691 fun(int a, int b) static int m, i=2; i+=m+1; m=i+a+b; return(m); int main() int k=4,m=1,p; p=fun(k,m); cou
42、tpendl; p=fun(k,m); coutpendl; 0m4k4a1m1b p2i388120178 17817int main() fun(); fun(); void fun() static int a3=0,1,2; int i ; for(i =0; i 3; i +) ai +=ai ; for(i =0; i 3; i +) coutai ; coutendl; return; 0 12 a0 a1 a20240483.6.1 存儲類型存儲類型一個一個C+程序可以由多個源程序文件組成。多文件程序系統(tǒng)可程序可以由多個源程序文件組成。多文件程序系統(tǒng)可以通過以通過外部存儲類型外
43、部存儲類型的變量和函數(shù)來的變量和函數(shù)來共享共享某些數(shù)據(jù)和操作。某些數(shù)據(jù)和操作。在一個程序文件中定義的全局變量和函數(shù)缺省為外部的,即其作在一個程序文件中定義的全局變量和函數(shù)缺省為外部的,即其作用域可以延伸到程序的其他文件中。其他文件如果要使用這個文用域可以延伸到程序的其他文件中。其他文件如果要使用這個文件中定義的全局變量和函數(shù),應該在使用前用件中定義的全局變量和函數(shù),應該在使用前用“extern”作外部聲作外部聲明。外部聲明通常放在文件的開頭(明。外部聲明通常放在文件的開頭(函數(shù)函數(shù)總是總是省略省略extern)。)。外部變量聲明不同于全局變量定義,變量定義時編譯器為其分外部變量聲明不同于全局變
44、量定義,變量定義時編譯器為其分配存儲空間,而變量聲明則表示該全局變量已在其他地方定義配存儲空間,而變量聲明則表示該全局變量已在其他地方定義過,編譯系統(tǒng)不再分配存儲空間。過,編譯系統(tǒng)不再分配存儲空間。外部的全局變量或函數(shù)加上外部的全局變量或函數(shù)加上static修飾,就成為靜態(tài)全局變量修飾,就成為靜態(tài)全局變量或靜態(tài)函數(shù)。靜態(tài)的全局變量和函數(shù)作用域限制在本文件,其或靜態(tài)函數(shù)。靜態(tài)的全局變量和函數(shù)作用域限制在本文件,其他文件即使使用外部聲明也無法使用該全局變量或函數(shù)。他文件即使使用外部聲明也無法使用該全局變量或函數(shù)。 【例【例3.11】外部存儲類型的例子外部存儲類型的例子全局變量的static:如果程
45、序是由多個源文件組成時,此全局變量的作用域只限于本文件中。extern int x; int x;main() a1.cppstatic char cc; extern int x; a2.cpp extern char cc; a3.cpp3.6.2 生命期生命期1.1. 靜態(tài)生命期靜態(tài)生命期 靜態(tài)生命期靜態(tài)生命期(Static extent或或Static storage duration)指)指的是標識符從程序開始運行時就存在,具有存儲空間,到程的是標識符從程序開始運行時就存在,具有存儲空間,到程序運行結(jié)束時消亡,釋放存儲空間。具有靜態(tài)生命期的標識序運行結(jié)束時消亡,釋放存儲空間。具有靜態(tài)
46、生命期的標識符存放在全局數(shù)據(jù)區(qū),如符存放在全局數(shù)據(jù)區(qū),如全局變量、靜態(tài)全局變量、靜態(tài)局全局變量、靜態(tài)全局變量、靜態(tài)局部變量部變量。具有靜態(tài)生命期的標識符在未被用戶初始化的情況。具有靜態(tài)生命期的標識符在未被用戶初始化的情況下,系統(tǒng)會自動將其初始化為下,系統(tǒng)會自動將其初始化為0。 函數(shù)駐留在代碼區(qū),也具有靜態(tài)生命期。所有具有文件函數(shù)駐留在代碼區(qū),也具有靜態(tài)生命期。所有具有文件作用域的標識符都具有靜態(tài)生命期。作用域的標識符都具有靜態(tài)生命期。 3.6.2 生命期生命期2. 2. 局部生命期局部生命期 在函數(shù)內(nèi)部或塊中定義的標識符具有在函數(shù)內(nèi)部或塊中定義的標識符具有局部生命期局部生命期(Automati
47、c extent或或Automatic storage duration),),其生命期開始于執(zhí)行到該函數(shù)或塊的標識符定義處,其生命期開始于執(zhí)行到該函數(shù)或塊的標識符定義處,結(jié)束于該函數(shù)或塊的結(jié)束處。具有局部生命期的標識結(jié)束于該函數(shù)或塊的結(jié)束處。具有局部生命期的標識符存放在棧區(qū)。具有局部生命期的標識符如果未被初符存放在棧區(qū)。具有局部生命期的標識符如果未被初始化,其內(nèi)容是隨機的,不可引用。始化,其內(nèi)容是隨機的,不可引用。 具有局部生命期的標識符必定具有局部作用域;具有局部生命期的標識符必定具有局部作用域;但反之不然,但反之不然,靜態(tài)局部變量靜態(tài)局部變量具有局部作用域,但卻具具有局部作用域,但卻具有
48、靜態(tài)生命期。有靜態(tài)生命期。3.6.2 生命期生命期具有具有動態(tài)生命期動態(tài)生命期(dynamic extent或或dynamic storage duration)的標識符存放在自由存儲區(qū),)的標識符存放在自由存儲區(qū),由特定的函數(shù)調(diào)用或運算來創(chuàng)建和釋放,如用由特定的函數(shù)調(diào)用或運算來創(chuàng)建和釋放,如用new運算符(或調(diào)用運算符(或調(diào)用malloc()函數(shù))為變量分配函數(shù))為變量分配存儲空間時,變量的生命期開始,而用存儲空間時,變量的生命期開始,而用delete運運算符(或調(diào)用算符(或調(diào)用free()函數(shù))釋放空間或程序結(jié)束函數(shù))釋放空間或程序結(jié)束時,變量生命期結(jié)束。關(guān)于時,變量生命期結(jié)束。關(guān)于new
49、運算符和運算符和delete運算符將在第七章中介紹。運算符將在第七章中介紹。3. 3. 動態(tài)生命期動態(tài)生命期3.7 函數(shù)的遞歸調(diào)用函數(shù)的遞歸調(diào)用1n 1)!-(n*n1n 1 0n 1 n! 遞歸是一種描述問題的方法,或稱算法。遞歸的思想遞歸是一種描述問題的方法,或稱算法。遞歸的思想可以簡單地描述為可以簡單地描述為“自己調(diào)用自己自己調(diào)用自己”。例如用如下方法定。例如用如下方法定義階乘:義階乘:可以看出是用階乘定義階乘,這種自己定義可以看出是用階乘定義階乘,這種自己定義自己的方法稱為遞歸定義。自己的方法稱為遞歸定義。遞歸的引入:遞歸的引入:遞歸定義的階乘函數(shù):遞歸定義的階乘函數(shù):fac(int
50、n)if (n=0|n=1) return 1;else return n*fac(n-1);只要設(shè)計主函數(shù)調(diào)用階乘函數(shù),即可實現(xiàn)計算階乘。只要設(shè)計主函數(shù)調(diào)用階乘函數(shù),即可實現(xiàn)計算階乘。3.7 函數(shù)的遞歸調(diào)用函數(shù)的遞歸調(diào)用【例【例3.12】 求求4!運行結(jié)果:運行結(jié)果:4321126244!=24說明:說明:cout”n4!=”fac(4)endl;執(zhí)行時是先算函數(shù)值,然后再從左到右輸出各表達式的值。執(zhí)行時是先算函數(shù)值,然后再從左到右輸出各表達式的值。所以有兩行輸出,而不是第一行插在第二行賦值號與所以有兩行輸出,而不是第一行插在第二行賦值號與24之間。之間。3.7 函數(shù)的遞歸調(diào)用函數(shù)的遞歸調(diào)用
51、探討:探討:計算是先右后左。請看下一條輸出語句:計算是先右后左。請看下一條輸出語句:cout”n4!=”fac(4) ”n3!=”fac(3)=0&ch=9?1:0;int main() char ch; while(cin.get(ch), ch!= n) if (IsNumber(ch) cout是數(shù)字字符是數(shù)字字符 endl; else cout不是數(shù)字字符不是數(shù)字字符 endl; return 0;因使用頻度很高,說明為內(nèi)聯(lián)函數(shù)。因使用頻度很高,說明為內(nèi)聯(lián)函數(shù)。3.9 頭文件與多文件結(jié)構(gòu)頭文件與多文件結(jié)構(gòu) (選讀)(選讀)3.9.1 頭文件頭文件標準庫頭文件:標準庫頭文件:考慮標識符在
52、其他文件中的可見性。使用頭文件是很有效的方考慮標識符在其他文件中的可見性。使用頭文件是很有效的方法。如:法。如:#includeusing namespace std; 其中的其中的iostream是是在在標準名字空間域標準名字空間域std中定義的頭文件。對中定義的頭文件。對應的傳統(tǒng)方式的文件名為應的傳統(tǒng)方式的文件名為,頭文件以,頭文件以“.h”為后綴為后綴。 系統(tǒng)定義的頭文件系統(tǒng)定義的頭文件中定義了一些常用的公用標識符和函數(shù)中定義了一些常用的公用標識符和函數(shù),用戶只要將頭文件包含進自己的文件,就可使頭文件中定義,用戶只要將頭文件包含進自己的文件,就可使頭文件中定義的標識符在用戶文件中變得可見
53、,也就可以直接使用頭文件中的標識符在用戶文件中變得可見,也就可以直接使用頭文件中定義的標識符和函數(shù)。定義的標識符和函數(shù)。 3.9.1 頭文件頭文件自定義頭文件:自定義頭文件:除了系統(tǒng)定義的頭文件外,用戶還可以除了系統(tǒng)定義的頭文件外,用戶還可以自定義頭文件自定義頭文件。對于具有外部存儲類型的標識符,可以在其他任何。對于具有外部存儲類型的標識符,可以在其他任何一個源程序文件中經(jīng)聲明后引用,因此用戶完全可以一個源程序文件中經(jīng)聲明后引用,因此用戶完全可以將一些具有將一些具有外部存儲類型的標識符的聲明外部存儲類型的標識符的聲明放在一個頭放在一個頭文件中。具體地說,頭文件中可以包括:文件中。具體地說,頭文
54、件中可以包括:用戶構(gòu)造的用戶構(gòu)造的數(shù)據(jù)類型(如枚舉類型),外部變量,外部函數(shù)、常數(shù)據(jù)類型(如枚舉類型),外部變量,外部函數(shù)、常量和內(nèi)聯(lián)函數(shù)等具有一定通用性或常用的量,量和內(nèi)聯(lián)函數(shù)等具有一定通用性或常用的量,而一般而一般性的變量和函數(shù)定義不宜放在頭文件中。性的變量和函數(shù)定義不宜放在頭文件中。3.9.2 多文件結(jié)構(gòu)多文件結(jié)構(gòu) 在開發(fā)較大程序時,通常將其分解為多個源程序文件在開發(fā)較大程序時,通常將其分解為多個源程序文件,每個較小的程序用一個源程序文件建立。程序經(jīng)過建立,每個較小的程序用一個源程序文件建立。程序經(jīng)過建立、編譯、連接,成為一個完整的可執(zhí)行程序。、編譯、連接,成為一個完整的可執(zhí)行程序。多文
55、件結(jié)構(gòu)多文件結(jié)構(gòu)通過工程進行管理,在工程中建立若干用戶定義的頭文件通過工程進行管理,在工程中建立若干用戶定義的頭文件.h和源程序文件和源程序文件.cpp。頭文件中定義用戶自定義的數(shù)據(jù)類。頭文件中定義用戶自定義的數(shù)據(jù)類型,所有的程序?qū)崿F(xiàn)則放在不同的源程序文件中型,所有的程序?qū)崿F(xiàn)則放在不同的源程序文件中。編譯時。編譯時每個源程序文件單獨編譯,如果源程序文件中有編譯預處每個源程序文件單獨編譯,如果源程序文件中有編譯預處理指令,則首先經(jīng)過編譯預處理生成臨時文件存放在內(nèi)存理指令,則首先經(jīng)過編譯預處理生成臨時文件存放在內(nèi)存,之后對臨時文件進行編譯生成目標文件,之后對臨時文件進行編譯生成目標文件.obj,編
56、譯后臨,編譯后臨時文件撤銷。所有的目標文件經(jīng)連接器連接最終生成一個時文件撤銷。所有的目標文件經(jīng)連接器連接最終生成一個完整的可執(zhí)行文件完整的可執(zhí)行文件.exe。 圖圖3.11是一個多文件系統(tǒng)的開發(fā)過程。是一個多文件系統(tǒng)的開發(fā)過程。3.9.2 多文件結(jié)構(gòu)多文件結(jié)構(gòu) 編譯 預編譯編譯 預編譯 預編譯編譯圖圖3.11 C+程序開發(fā)過程程序開發(fā)過程file1.hfile1.cppfile2.hfile2.cppfilen.hfilen.cpp臨時文件臨時文件1臨時文件臨時文件2臨時文件臨時文件nfile1.objfile2.objfilen.objFilename.exe.libC+標準類庫標準類庫連接
57、連接運行運行3.10 編譯預處理編譯預處理(選讀選讀) 3.10.1 宏定義指令宏定義指令 3.10.2 文件包含指令文件包含指令 3.10.3 條件編譯指令條件編譯指令 3.10.1 宏定義指令宏定義指令1 1 不帶參宏定義不帶參宏定義用來產(chǎn)生與一個字符串對應的常量字符串,格式為:用來產(chǎn)生與一個字符串對應的常量字符串,格式為:#define #define 宏名宏名 常量串常量串 預處理后文件中凡出現(xiàn)該字符串處均用其對應的常量預處理后文件中凡出現(xiàn)該字符串處均用其對應的常量串代替。替換過程稱為宏替換或宏展開。例如,如果串代替。替換過程稱為宏替換或宏展開。例如,如果使用指令使用指令#define
58、 PI 3.1415926#define PI 3.1415926則程序中可以使用標識符則程序中可以使用標識符PIPI,編譯預處理后產(chǎn)生一個,編譯預處理后產(chǎn)生一個中間文件,文件中所有中間文件,文件中所有PIPI被替換為被替換為3.14159263.1415926。宏替換只是字符串和標識符之間的簡單替換,預處理宏替換只是字符串和標識符之間的簡單替換,預處理本身不做任何數(shù)據(jù)類型和合法性檢查,也不分配內(nèi)存本身不做任何數(shù)據(jù)類型和合法性檢查,也不分配內(nèi)存單元單元。3.10.1 宏定義指令宏定義指令2 2 帶參數(shù)的宏定義帶參數(shù)的宏定義帶參宏定義的形式很象定義一個函數(shù),格式為:帶參宏定義的形式很象定義一個函
59、數(shù),格式為:#define 宏名宏名 ( 形參表形參表 ) 表達式串表達式串 例如作如下宏定義:例如作如下宏定義:#define S(a,b) (a)*(b)/2程序中可使用程序中可使用S(a,b),預處理后產(chǎn)生中間文件,其中,預處理后產(chǎn)生中間文件,其中S(a,b)被被替換成替換成(a)*(b)/2。注意,宏定義時形參通常要用括號括起來。注意,宏定義時形參通常要用括號括起來,否則容易導致邏輯錯誤。例如,如果定義:,否則容易導致邏輯錯誤。例如,如果定義:#define S(a,b) a*b/2那么程序中的那么程序中的S(3+5,4+2)就會被宏展開為就會被宏展開為3+5*4+2/2,不,不符合定
60、義的真正的意圖。符合定義的真正的意圖。帶參宏定義形式上象定義函數(shù),但它與函數(shù)的本質(zhì)不同,宏定帶參宏定義形式上象定義函數(shù),但它與函數(shù)的本質(zhì)不同,宏定義仍然只是產(chǎn)生字符串替代,不存在分配內(nèi)存和參數(shù)傳遞。義仍然只是產(chǎn)生字符串替代,不存在分配內(nèi)存和參數(shù)傳遞。 3.10.2 文件包含指令文件包含指令文件包含文件包含用用#include指令指令,預處理后將指令中指明的源程序,預處理后將指令中指明的源程序文件嵌入到當前源程序文件的指令位置處。格式為:文件嵌入到當前源程序文件的指令位置處。格式為:#include 或或#include 文件名文件名第一種第一種方式稱為方式稱為標準方式標準方式,預處理器將在,預
61、處理器將在include子目錄下子目錄下搜索由文件名所指明的文件。這種方式適用于嵌入搜索由文件名所指明的文件。這種方式適用于嵌入C+提供提供的頭文件,因為這些頭文件一般都存在的頭文件,因為這些頭文件一般都存在C+系統(tǒng)目錄的系統(tǒng)目錄的include子目錄下。而子目錄下。而第二種方式第二種方式編譯器將首先在當前文件編譯器將首先在當前文件所在目錄下搜索,如果找不到再按標準方式搜索。這種方式所在目錄下搜索,如果找不到再按標準方式搜索。這種方式適用于嵌入用戶自己建立的頭文件。適用于嵌入用戶自己建立的頭文件。一個被包含的頭文件中還可以有一個被包含的頭文件中還可以有#include指令,指令,即即inclu
62、de指令可以嵌套指令可以嵌套,但是,如果同一個頭文,但是,如果同一個頭文件在同一個源程序文件中被件在同一個源程序文件中被重復包含重復包含,就會出現(xiàn),就會出現(xiàn)標標識符重復定義的錯誤識符重復定義的錯誤。例如:頭文件。例如:頭文件f2.h中包含了中包含了f1.h,如果文件,如果文件f3.cpp中既包含中既包含f1.h,又包含,又包含f2.h,那么編譯將提示錯誤,原因是那么編譯將提示錯誤,原因是f1.h被包含了兩次,被包含了兩次,那么其中定義的標識符在那么其中定義的標識符在f3.cpp中就被重復定義。中就被重復定義。避免重復包含可以用避免重復包含可以用條件編譯指令條件編譯指令。3.10.2 文件包含指
63、令文件包含指令3.10.3 條件編譯指令條件編譯指令 1 用用宏名宏名作為編譯的條件作為編譯的條件格式為:格式為:#ifdef#else#endif2 表達式的值表達式的值作為編譯條件作為編譯條件格式為:格式為:#if #else#endif當希望在不同條件下編譯程序的不同部分。這種情況就要使當希望在不同條件下編譯程序的不同部分。這種情況就要使用條件編譯指令。用條件編譯指令。 其中程序段可以是程序也可以是編譯預處理指令??梢酝ㄟ^其中程序段可以是程序也可以是編譯預處理指令??梢酝ㄟ^在該指令前面安排宏定義來控制編譯不同的程序段。在該指令前面安排宏定義來控制編譯不同的程序段。例:在調(diào)試程序時常常要輸
64、出調(diào)試信息,而調(diào)試完后不需要例:在調(diào)試程序時常常要輸出調(diào)試信息,而調(diào)試完后不需要輸出這些信息,則可以把輸出調(diào)試信息的語句用條件編譯指輸出這些信息,則可以把輸出調(diào)試信息的語句用條件編譯指令括起來。形式如下:令括起來。形式如下:#ifdef DEBUGcouta=atx=xendl;#endif在程序調(diào)試期間,在該條件編譯指令前增加宏定義:在程序調(diào)試期間,在該條件編譯指令前增加宏定義:#define DEBUG調(diào)試好后,刪除調(diào)試好后,刪除DEBUG宏定義,將源程序重新編譯一次。宏定義,將源程序重新編譯一次。條件編譯指令包括:條件編譯指令包括:#if、#else、#ifdef、#ifndef、#en
65、dif、#undef等。等。#ifndef與與#ifdef作用一樣,只是選擇的條件相反。作用一樣,只是選擇的條件相反。#undef指令用來取消指令用來取消#define指令所定義的符號,這樣指令所定義的符號,這樣可以根據(jù)需要打開和關(guān)閉符號??梢愿鶕?jù)需要打開和關(guān)閉符號。第三章第三章 函數(shù)函數(shù)再見謝謝!謝謝!3.1.3 函數(shù)的調(diào)用函數(shù)的調(diào)用【例【例3.1】 main( )函數(shù)函數(shù)調(diào)用調(diào)用max(2.5,4.7 )函數(shù)函數(shù)max(2.5,4.7 )return 4.7 主程序后主程序后續(xù)語句續(xù)語句【例【例3.1】 輸入兩個實數(shù),輸出其中較大的數(shù)。其中輸入兩個實數(shù),輸出其中較大的數(shù)。其中求兩個實數(shù)中的
66、較大數(shù)用函數(shù)完成。求兩個實數(shù)中的較大數(shù)用函數(shù)完成。程序如下程序如下:#include using namespace std;float max(float a,float b)return(a=b?a:b);int main()float x,y;cout輸入兩個實數(shù):輸入兩個實數(shù):xy;coutx和和y中較大數(shù)為中較大數(shù)為max(x,y)endl;return 0;形式參數(shù)形式參數(shù)實際參數(shù)實際參數(shù) 3.2.1 函數(shù)的參數(shù)傳遞及傳值調(diào)用函數(shù)的參數(shù)傳遞及傳值調(diào)用【例【例3.2】 調(diào)用調(diào)用power(4.6,3 )函數(shù)函數(shù)power(4.6,3 )return 97.336 主程序后續(xù)語主程序后續(xù)語句句n= 3x= 4.6c= a【例【例3.2】 實參和形參對應關(guān)系的示例。實參和形參對應關(guān)系的示例。float power(float x,int n) /求求x x的的n n次冪次冪float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower(x,n)=power(x,n)endl;c
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。