詳解C語言函式

weixin_33895657發表於2017-09-23

函式的定義

函式的定義如下:

型別  函式名(形式引數)
{
   程式碼塊
}

程式碼塊包含了區域性變數的宣告函式呼叫所要執行的語句

return語句

return 語句的語法如下:

return expression;

  當執行流執行到return語句時函式被返回到被呼叫的地方,return語句允許在任何地方返回,並不要一定在函式的末尾。
  表示式expression是可選的,如果函式不需要向呼叫程式返回一個值,就可以被省略,這種沒有返回值的函式可以在宣告的時候將其函式的型別置為void
  函式是從內部表示式呼叫的,它必須返回一個值,用於表示式的求值,這類函式的return語句必須包含一個表示式,通常函式的型別就是表示式的型別。
只有當編譯器可以通過通常的算數轉化把表示式的型別轉化為正確的型別時,才允許返回值的型別與函式的型別不一致

函式的宣告

  如果沒有函式的宣告資訊,編譯器便假定這個函式的呼叫時的引數型別和數量是正確的,它同時假定函式的返回值型別是整型

原型

  向編譯器提供一些關於函式的資訊顯然是很安全的,我們可以通過兩種方法來實現:

  • 如果同一原始檔的前面已經出現過該函式的定義,編譯器會記住它的引數數量和型別,以及函式的返回值型別。接著編譯器會檢查該函式的後續呼叫,確保它們是正確的。
  • 向編譯器提供函式的原型,使用原型最安全的方法是把原型置於一個單獨的檔案,當其它檔案需要原型時,就使用#include指令包含改檔案。

  原型的定義如下:

int  *find_int(int key,int array[],int len);

  函式原型的使用如下:

#include "func.h"
void a()
{
  func(&a,b);
}
檔案func.h包含了函式func的宣告
int func(int *value,int len);

函式的原型同時也被#include包含到定義函式的檔案中,編譯器就可以確認函式的定義與函式的原型必須匹配

  區分函式原型函式定義的是後面那個分號(;)

函式的預設認定

  當函式呼叫一個無法見到原型的韓束時,編譯器認為該函式返回一個整型值。對於那些並不是返回值為整型值的函式呼叫,這可能引起錯誤。

值的型別並不是值得內在本質(固有屬性),而是取決於它使用的方式。

函式的引數

兩個概念:
1.傳值呼叫:傳遞給被呼叫函式的是實參的一份拷貝,函式可以放心的修改這個拷貝值,而不用擔心會修改呼叫程式實際傳遞給它的引數。
2.傳址呼叫:傳遞給被呼叫函式的是指標的一份拷貝,假如傳遞的是陣列名,並且在函式中使用下標引用該陣列的值,那麼在函式中對陣列元素的修改其實修改的是呼叫程式中的陣列元素,陣列並不會複製。

陣列引數的這種行為似乎與傳值呼叫相悖,其實不然,陣列名其實就是一個指標,傳遞函式的就是該指標的一份拷貝,下標應用也是間接訪問的一種,所以這份拷貝進行間接訪問操作訪問的是原先的陣列

總結

  • 傳遞給函式的標量都是傳值呼叫
  • 傳遞給函式的陣列引數在行為上就像他們是通過傳址呼叫一樣。

可變引數列表

  讓一個函式在不同的時刻接受不同數目的引數。

stdarg巨集

  可變引數列表是通過巨集來實現的,這些巨集位於stdarg.h,這個標頭檔案宣告瞭一個型別va_list和三個巨集——va_start,va_arg,va_end
  可變引數列表實現的步驟

  • 用型別va_list宣告一個變數var_arg,它用於訪問引數列表的未定部分;
  • var_arg變數用va_start來初始化,它的第一個引數是va_list變數,第二個引數是省略號前最後一個有名字的引數,初始化過程把var_arg變數設定為指向可變引數部分的第一個引數;
  • 用va_arg訪問引數,這個巨集接受兩個引數,va_list變數和引數列表中下一個引數的型別
  • 當訪問完引數後,呼叫va_end;

例項演示:求平均數

#include<stdarg.h>
float average(int n_values,...)
{
  valist var_arg;    //宣告va_list型別的變數
  int count;
  float sum = 0;
  /*
  *準備訪問可變引數
  */
 va_start(var_arg,n_values);
    /*
  *新增自可變數列表
  */
  for(count = 0;count < n_values;count++ )
  {
   sum += va_arg(var_arg,int);
  }
  va_end(var_arg);
  return sum / n_values;
}

相關文章