1. 程式人生 > >C-學習筆記5

C-學習筆記5

 函式

1.函式的定義

        函式型別 函式名(型別名 形式引數1,型別名 形式引數2 ...)

        {

                說明部分

                語句部分

        }

2.在C語言中,規定函式不允許巢狀定義,即在定義一個函式時,不能在該函式體裡包含另一個函式的定義。但是可以巢狀呼叫,即在一個函式的執行過程中可以呼叫另一個函式。

3.變數的儲存類別及生命週期

       從變數值生存週期來分,可以將變數分為靜態儲存變數和動態儲存變數。靜態儲存變數是指程式執行時固定分配儲存空間的變數。動態儲存變數是在程式執行時根據需要動態分配儲存空間的變數。

         程式執行時的記憶體分配有以下5種:系統區、程式程式碼區、靜態資料區、動態資料區、自由空間。全域性變數和靜態的區域性變數存放在靜態資料區,在程式開始時給它們分配記憶體空間,程式執行完畢就釋放。在程式執行過程中它們佔據固定的儲存單元,它們的生命週期貫穿程式的整個過程。

         動態資料存放的資料為自動區域性變數、形參變數和中斷的現場保護的資料。自動區域性變數指的是未加static的區域性變數,形式參量指的是函式形式引數,中斷的現場保護的資料是指在函式呼叫的現場保護和返回地址。在函式開始呼叫是分配動態儲存空間,函式結束時釋放這些空間,他們的生命週期為函式的整個過程。

           因此,變數完整的定義方式為:儲存類別 資料型別識別符號 變數名;

          儲存類別共有四種:auto——自動變數;static——靜態變數;register——暫存器變數;extern——外部變數。

(1).auto變數(自動變數)

          當局部變數定義時使用auto標籤或沒有指定儲存類別時,系統就認為所定義的變數是自動變數。系統對自動變數是動態分配儲存空間的,資料儲存在動態資料區中。區域性變數的定義必須放在函式體或者複合體中所有可執行語句之前。自動變數的作用域是從定義的位置起,到函式體或者複合體結束為止。它的儲存單元在進入這些區域性變數所在的函式或複合體時生成,退出其所在函式體或複合體時消失,這就是自動變數的生存週期。當再次進入函式體時,系統將為他們另行分配儲存單元。

(2).register變數(暫存器變數)

         暫存器變數也是自動變數,它與自動變數的區別僅在於:用register說明的變數建議編譯程式將變數的值保留在CPU的暫存器中,而不像一般變數那樣,佔用記憶體單元。區域性變數的定義必須放在函式體或者複合體中所有可執行語句前。

           說明:

① 只有函式內定義的變數或者形參可以定義為暫存器變數。暫存器變數的值儲存在CPU的中。

② 受暫存器長度的限制,暫存器變數只能是char,int和指標型別的變數;對於佔用位元組數多的變數(long、float、double等)及陣列不宜定義為暫存器變數。

③ 由於暫存器變數值儲存在CPU的暫存器中,系統從CPU的暫存器中讀寫變數比記憶體要快,所以將使用頻率比較高的變數設定為暫存器變數。例如for迴圈中所用到的變數。

④當今的優化編譯系統能夠識別使用頻率較高的變數,從而自動地將這些變數放在暫存器中,因而一般不需要由程式設計師指定。

注:暫存器是CPU的一部分,暫存器是有限儲存容量的高速儲存部件,它們可用來暫存指令、地址和資料。

(3).static變數(靜態變數)

          a.靜態區域性變數

         在函式體或內部使用static說明的變數,稱靜態全域性變數。它分配在記憶體的靜態資料儲存區。它的生存期與作用域是全域性壽命,區域性可見。即只有在編譯時可以賦值,以後每次呼叫時不再分配記憶體單元和初始化,只是保留上一次函式呼叫結束的值,直到程式執行結束,對應的記憶體單元才釋放,而其作用域僅僅只限於所定義的函式和複合體。  

           注:變數沒有賦初值時,auto變數是個隨機值,static變數是0。

          例:

          void f1()

          {

                  auto int x = 1;

                  printf("x=%d",x);

          }

          void f2()

          {

                  static int x = 1;

                  x++;

                  printf("x=%d",x);

          }

          int main()

         {

                f1();  f2();

                f1();  f2();

         }

         結果為 x=1 x=2

                     x=1 x=3

         b.靜態全域性變數

         在所有函式(包括主函式)之外的用static說明的變數,稱為靜態全域性變數。它分配在記憶體的靜態資料儲存區,它的生存期與作用域是全域性壽命,區域性可見。即在整個程式執行期間都存在;但它與外部變數(即全域性變數)不同,靜態全域性變數只能在所定義的檔案中使用,具有區域性可見性(與靜態區域性變數的區域性可見性不同),而外部變數可在其他檔案中使用。

(4).extern變數(外部變數)

        外部變數(即全域性變數)是在所有函式(包括主函式)外部定義的變數,它的作用域為從變數定義處開始,到本程式檔案的末尾。如果外部末尾不在檔案開頭定義,其有效的作用範圍只限於定義處到檔案終了。如果定義點之前的函式想引用該外部變數,則應該引用之前用關鍵字extern對該變數作"外部變數宣告"。表示該變數是一個已經定義的外部變數。有了此宣告,就可以從"宣告"處起,合法地使用該外部變數。

4.外部函式和內部函式

         a.外部函式

              (1).不作任何標示的函式,允許被其他源程式檔案中的函式呼叫;但必須在呼叫的原始檔中做外部函式宣告,即在宣告時加上extern關鍵字。

             extern 函式型別 函式名(資料型別 形式引數1,資料型別 形式引數2,...)

              (2).在定義函式時,在函式的首位加上extern關鍵字,表示該函式是外部函式,可以被其他的檔案呼叫。

             extern 函式型別 函式名(資料型別 形式引數1,資料型別 形式引數2,... ) 

             {

                     函式體

             }

             外部函式的呼叫方式

             file1.c                                                 file2.c

             extern int function1()                          a = function1();

      或

             int function1()                                    extern int function1();

                                                                       a = function1();

      b.內部函式

            如果在一個原始檔中定義的函式只能被本檔案中的函式呼叫,而不能被同一源程式其他檔案中的函式呼叫,這種函式稱為內部函式。

            內部函式是用static標示的函式,只能被本源程式檔案中的函式呼叫,定義形式為:

             static 函式型別 函式名(資料型別 形式引數1,資料型別 形式引數2,... ) 

             {

                     函式體

             }

5.編譯預處理

        編譯預處理對源程式編譯之前做一些處理:生成擴充套件C源程式。

        1.編譯預處理種類

            巨集定義       #define

            檔案包含   #include

            條件編譯   #if-#else-#endif

         2.帶參的巨集定義

            #define POWER(x) x*x

帶參的巨集定義和函式之間的聯絡與區別
帶參巨集 函式
處理時間 編譯時 程式執行時
引數型別 無型別問題 定義實參,形參型別
處理過程

不分配記憶體

簡單的字元置換

分配記憶體先求實參值

再代入形參

程式長度 變長 不變
執行速度 不佔執行時間 呼叫和返回佔時間

6.注:

       ① 每個函式都有堆疊區。堆疊區是計算機的記憶體用來儲存函式的變數和引數。

       ② 遞迴函式必須定義出口,否則會導致系統宕機