函數宣告與定義
初寫:2005.05.11, 更新日期:2015.05.22
 
作者:曾聖超老師
 
  • 函數宣告:跟宣告變數一樣,是在告訴C語言編譯器,有某一個函數可以使用。
    而此函數是在main之前,還是之後,抑或是另一個檔案中,也可從宣告狀況來確認。

  • 函數於main前定義:


  • 於main後定義:
    主程式 main( )若寫在函數之前,則必須先對函數宣告。


    在程式呼叫的地方(引用函數),稱之為引數(argument),
    或稱實際引數(actual argument)或實際參數(actual parameter)。

  • 函數定義:即是函數的結構,語法架構如下:
    回傳型態  函數名稱(資料型態  形式參數名稱, ... ){
      區域變數宣告;
      ...
      return  回傳值或算式;
    }

    在函數撰寫的地方(實際函數)的刮號內,稱為參數(parameter),
    或稱形式參數(formal parameter)。

    例如:
    實際引數 y=square(x);
    形式參數 float square(float x)
    若以練習1為例,實際引數為a,而形式參數為y。

    基本上,只要資料型態裡可以定義的,如:變數、指標、陣列等,函數(含主程式main)都可以 作傳遞。


  • 範例1:
    假設我們想要製作一個求平方的函數F(x)= 或 y =,設定函數名稱為square(x)
    函數宣告:
     float square( float x );

    函數可寫成:
     float square( float x )
     {
         return x*x;
     } 

  • 練習1:


  • 兩個(或多個)變數傳遞
    函數宣告:
     float  atest( int x, int y, float z);

    函數可寫成:
     float  atest( int x, int y, float z)
     {
         return x*y+z;
     } 
  • 練習2:
    函數 p( x, y ) = x3 + 3 x2 y + 3 x y2 + y3
    請寫出其宣告與定義(於筆記),整數或浮點數皆可。

  • 練習3:
    請寫一個可以計算整數次方的函數index(int a, int b)
    說明:前面在講解運算式時,談到a3需使用a*a*a來製作時,
    有同學提出疑問,那如果做a10,不就得手工複製*a好多次!?
    學過迴圈語法後,我們可以使用函數撰寫這樣的程式碼。
    以上述的例子,撰寫一個求ab次方的index函數,
    看看是否能夠讓它運作!
    請將函式程式碼寫講義上。



 延伸概念
傳值呼叫(call by value):
在程式呼叫之處,將實際引數的值copy給函數裡的形式參數,在函數裡作運算或改變,並不會影響 呼叫位置的引數。

傳址呼叫(call by address)/傳參呼叫(call by reference):
將程式呼叫之實際引數的位址,傳遞給函數中對應的變數或指標,所以在被呼叫之函數裡,去修改參數時,將會改變 所呼叫引數的值。
C語言以「指標」實作傳址呼叫的媒介。

set1(int x, int y) /* 傳值  */
{
   x = 4;
   y = 5;
}

set2(int *x, int *y) /* 傳址 */
{
   *x = 6;
   *y = 7;
}

main()
{
   int x =2, y=3; // 變數宣告
   printf(" 初值 X=%d Y=%d\n", x, y);
   set1(x, y); // 呼叫傳值函數(交換X Y)
   printf(" set1傳值 X=%d Y=%d\n",x,y);
   set2(&x, &y); // 呼叫傳址函數(交換X Y)
   printf(" set2傳址 X=%d Y=%d\n",x,y);
}
請問執行的結果是什麼呢?
照理說,執行set1後,x,y的值應該被改成4,5,但結果仍是2,3
表示主程式main裡的x,y沒有被修改。
但執行set2後,可發現x,y值被改成6,7
也就是傳址呼叫後,被呼叫的函數裡修改變數的話,
也會異動到主程式main的x,y數值。

參考資料: