[C++]函式與編譯預處理(一)
函式與編譯預處理
概述
·函式是程式程式碼的一個自包含單元,用於完成某一特定的任務。
·C++是由函式構成的,函式是C++的基本模組。
·有的函式完成某一操作;有的函式計算出一個值。通常,一個函式即能完成某一特定操作,
又能計算數值。
為什麼要使用函式?
1、避免重複的程式設計。
2、使程式更加模組化,便於閱讀、修改。
所編寫的函式應儘量少與主調函式發生聯絡,這樣便於移植。
說明:
1、一個源程式檔案由一個或多個函式組成,編譯程式以檔案而不是以函式為單位進行編譯的。
2、一個程式可以由多個原始檔組成,可以分別編譯,統一執行。
3、一個程式必須有且只有一個main( )函式,C++從main( )函式開始執行。
4、C++語言中,所有函式都是平行獨立的,無主次、相互包含之分。函式可以巢狀呼叫,不可巢狀定義。
5、從使用角度來說,分標準函式和使用者自定義函式;從形式來說,分無參函式和有參函式。
庫函式是C++編譯系統已預定義的函式,使用者根據需要可以直接使用這類函式。庫函式也稱為標準函式。
為了方便使用者進行程式設計,C++把一些常用數學計算函式(如sqrt()、exp()等)、字串處理函式、標準輸入輸出函式等,都作為庫函式提供給使用者,使用者可以直接使用系統提供的庫函式。
庫函式有很多個,當使用者使用任一庫函式時,在程式中必須包含相應的標頭檔案。 如 #include<iostream.h>等。
使用者在設計程式時,可以將完成某一相對獨立功能的程式定義為一個函式。使用者在程式中,根據應用的需要,由使用者自己定義函式,這類函式稱為使用者自定義的函式。
根據定義函式或呼叫時是否要給出引數,又可將函式分為:無參函式和有參函式。
函式定義的一般形式
一、無參函式
主調函式並不將資料傳給被調函式。
無參函式主要用於完成某一操作。
輸出: * * * * * * * * * * *
How do you do!
* * * * * * * * * * *
二、有參函式
主調函式和被調函式之間有資料傳遞。主調函式可以將引數傳遞給被調函式,被調函式中的結果也可以帶回主調函式。
型別說明 函式名(形式引數列表說明 )
{ 函式體 }
函式引數和函式的值
形參是被調函式中的變數;實參是主調函式賦給被調函式的特定值。實參可以是常量、變數或複雜的表示式,不管是哪種情況,在呼叫時實參必須是一個確定的值。
形參與實參型別相同,一一對應。
形參必須要定義型別,因為在定義被調函式時,不知道具體要操作什麼數,而定義的是要操作什麼型別的數。
說明:
1、在未出現函式呼叫時,形參並不佔記憶體的儲存單元,只有在函式開始呼叫時,形參才被分配記憶體單元。呼叫結束後,形參所佔用的記憶體單元被釋放。
2、實參對形參變數的傳遞是“值傳遞”,即單向傳遞。在記憶體中實參、形參分佔不同的單元。
3、形參只作用於被調函式,可以在別的函式中使用相同的變數名。
形參必須要定義型別,因為在定義被調函式時,不知道具體要操作什麼數,而定義的是要操作什麼型別的數。
形參是被調函式中的變數;實參是主調函式賦給被調函式的特定值。在函式呼叫語句中,實參不必定義資料型別,因為實參傳遞的是一個具體的值(常量),程式可依據這個數值的表面形式來判斷其型別,並將其賦值到對應的形參變數中。
函式的返回值
函式的返回值通過return語句獲得。函式只能有唯一的返回值。
函式返回值的型別就是函式的型別。
return語句可以是一個表示式,函式先計算表示式後再返回值。
return語句還可以終止函式,並將控制返回到主調函式。
一個函式中可以有一個以上的return語句,執行到哪一個return語句,哪一個語句起作用。
若函式體內沒有return語句,就一直執行到函式體的末尾,然後返回到主調函式的呼叫處。
既然函式有返回值,這個值當然應屬於某一個確定的型別,應當在定義函式時指定函式值的型別。
不帶返回值的函式可說明為void型。
函式的型別與函式引數的型別沒有關係。
double blink ( int a, int b)
如果函式的型別和return表示式中的型別不一致,則以函式的型別為準。函式的型別決定返回值的型別。對數值型資料,可以自動進行型別轉換。
在一個函式中呼叫另一函式(即被呼叫函式)需要具備哪些條件呢?
1) 被呼叫的函式必須是已存在的函式
2) 如果使用庫函式,必須用 #include < math.h>
3) 函式呼叫遵循先定義、後呼叫的原則,即被調函式應出現在主調函式之前。
4) 如果使用使用者自己定義的函式,而該函式與呼叫它的函式(即主調函式)在同一個程式單位中且位置在主調函式之後,則必須在呼叫此函式之前對被呼叫的函式作宣告。
函式的巢狀呼叫
C語言中,所有函式都是平行獨立的,無主次、相互包含之分。函式可以巢狀呼叫,不可巢狀定義。
在main函式中呼叫a函式,在a函式中又呼叫b函式。
函式的遞迴呼叫
在呼叫一個函式的過程中直接或間接地呼叫函式本身,稱為函式的遞迴呼叫。
作用域和儲存類
作用域是指程式中所說明的識別符號在哪一個區間內有效,即在哪一個區間內可以使用或引用該識別符號。在C++中,作用域共分為五類:塊作用域、檔案作用域、函式原型作用域、函式作用域和類的作用域。
塊作用域
我們把用花括號括起來的一部分程式稱為一個塊。在塊內說明的識別符號,只能在該塊內引用,即其作用域在該塊內,開始於識別符號的說明處,結束於塊的結尾處。
在一個函式內部定義的變數或在一個塊中定義的變數稱為區域性變數。
在函式內或複合語句內部定義的變數,其作用域是從定義的位置起到函式體或複合語句的結束。形參也是區域性變數。
主函式main中定義的變數,也只在主函式中有效,同樣屬於區域性變數。
不同的函式可以使用相同名字的區域性變數,它們在記憶體中分屬不同的儲存區間,互不干擾。
注意:
具有塊作用域的識別符號在其作用域內,將遮蔽其作用塊包含本塊的同名識別符號,即
變數名相同,區域性更優先。
檔案作用域
在函式外定義的變數稱為全域性變數。
全域性變數的作用域稱為檔案作用域,即在整個檔案中都是可以訪問的。
其預設的作用範圍是:從定義全域性變數的位置開始到該源程式檔案結束。
當在塊作用域內的變數與全域性變數同名時,區域性變數優先。
在同一個原始檔中,外部變數與區域性變數同名,則在區域性變數的作用範圍內,外部變數不起作用。
函式原型作用域
在函式原型的參數列中說明的識別符號所具有的作用域稱為函式原型作用域,它從其說明處開始,到函式原型說明的結束處結束。
float tt(int x , float y); //函式tt的原型說明
由於所說明的識別符號與該函式的定義及呼叫無關,所以,可以在函式原型說明中只作引數的型別說明,而省略參量名。
float tt (int , float);
儲存類
靜態儲存:在檔案執行期間有固定的儲存空間,直到檔案執行結束。
動態儲存:在程式執行期間根據需要分配儲存空間,函式結束後立即釋放空間。若一個函式在程式中被呼叫兩次,則每次分配的單元有可能不同。
動態區域性變數未被賦值時,其值為隨機值。其作用域的函式或複合語句結束時,空間被程式收回。
程式執行到靜態區域性變數時,為其在靜態區開闢儲存空間,該空間一直被保留,直到程式執行結束程式執行到靜態區域性變數時,為其在靜態區開闢儲存空間,該空間一直被保留,直到程式執行結束。
由於儲存在靜態區,靜態區域性變數或全域性變數未賦初值時,系統自動使之為0。
全域性變數的儲存方式(extern static)
全域性變數是在函式的外部定義的,編譯時分配在靜態儲存區,如果未賦初值,其值為0。
1、extern 儲存類別
全域性變數的預設方式,當在一個檔案中要引用另一個檔案中的全域性變數或在全域性變數定義之前要引用它時,可用extern作說明,相當於擴大全域性變數的作用域。
2、靜態(static)儲存類別
它僅能在本檔案中引用,即使在其它檔案中用extern說明也不能使用。相當於限制了全域性變數的作用域範圍。
靜態區域性變數:static 在函式內部定義,儲存在靜態儲存區,與auto對應,在別的函式中不能引用。
全域性靜態變數:static 在函式外部定義,只限在本檔案中使用,與extern對應。
當變數名相同致使作用域相重時,起作用的是最近說明的那個變數。
行內函數
行內函數的實質是用儲存空間(使用更多的儲存空間)來換取時間(減少執行時間).
行內函數的定義方法是,在函式定義時,在函式的型別前增加修飾詞inline。
使用行內函數時應注意以下幾點:
1、C++中,除在函式體內含有迴圈,switch分支和複雜巢狀的if語句外,所有的函式均可定義為行內函數。
2、行內函數也要定義在前,呼叫在後。形參與實參之間的關係與一般的函式相同。
3、對於使用者指定的行內函數,編譯器是否作為行內函數來處理由編譯器自行決定。說明行內函數時,只是請求編譯器當出現這種函式呼叫時,作為行內函數的擴充套件來實現,而不是命令編譯器要這樣去做。
4、正如前面所述,行內函數的實質是採用空間換取時間,即可加速程式的執行,當出現多次呼叫同一行內函數時,程式本身佔用的空間將有所增加。如上例中,行內函數僅呼叫一次時,並不增加程式佔用的儲存間。
具有預設引數值和引數個數可變的函式
在C++中定義函式時,允許給引數指定一個預設的值。在呼叫函式時,若明確給出了這種實參的值,則使用相應實參的值;若沒有給出相應的實參,則使用預設的值。
使用具有預設引數的函式時,應注意以下幾點:
1.不可以靠左邊預設
2.函式原型說明時可以不加變數名
3.只能在前面定義一次預設值,即原型說明時定義了預設值,後面函式的定義不可有預設值。
相關文章
- [C++]函式與編譯預處理(二)C++函式編譯
- c++進階(一)C語言條件編譯及編譯預處理階段C++C語言編譯
- C/C++預處理、編譯、連結過程【Z】C++編譯
- en_concat函式編譯失敗處理函式編譯
- GCC編譯過程(預處理->編譯->彙編->連結)GC編譯
- gcc 從語言編譯全過程 預處理---->編譯---->彙編----->連結GC編譯
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法編譯
- C++行內函數、函式過載與函式預設引數C++函數函式
- [譯] 如何使用純函式式 JavaScript 處理髒副作用函式JavaScript
- 異常處理與異常函式函式
- C++ 字元處理函式(cctype標頭檔案)C++字元函式
- 磁碟處理函式函式
- 字元處理函式字元函式
- 模板函式編譯原理函式編譯原理
- oracle函式大全-字串處理函式Oracle函式字串
- python函式每日一講 - divmod數字處理函式Python函式
- C++ 預編譯標頭檔案C++編譯
- 大話css預編譯處理(三):基礎語法篇CSS編譯
- 處理一些編譯警告的簡單編譯
- C++編譯器怎麼實現異常處理1 (轉)C++編譯
- C++編譯器怎麼實現異常處理3 (轉)C++編譯
- C++編譯器怎麼實現異常處理2 (轉)C++編譯
- 陣列處理函式陣列函式
- SqlServer——字串處理函式SQLServer字串函式
- Oracle函式-->字元處理Oracle函式字元
- 安全字串處理函式字串函式
- 檔案處理函式函式
- 時間處理函式函式
- C++常用字串處理函式及使用示例(轉)C++字串函式
- count函式與order by子句一起查詢時報錯處理函式
- 使用自定義函式實現資料編解碼、格式處理與業務告警函式
- C++中的預處理(上) (轉)C++
- C++中的預處理(下) (轉)C++
- PHP函式處理函式例項詳解PHP函式
- 編譯warp,d語言寫的c/c++前處理器.編譯C++
- 用預編譯去理解函式宣告提升和變數宣告提升編譯函式變數
- C++中函式指標與函式物件C++函式指標物件
- C++中的字串編碼處理C++字串編碼