詳解C語言函式
函式的定義
函式的定義如下:
型別 函式名(形式引數)
{
程式碼塊
}
程式碼塊包含了區域性變數的宣告和函式呼叫所要執行的語句。
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;
}
相關文章
- C 語言回撥函式詳解函式
- C語言解讀assert函式C語言函式
- C語言常用函式C語言函式
- C語言的函式C語言函式
- C語言 execve()函式C語言函式
- 08. C語言函式C語言函式
- C語言 函式指標C語言函式指標
- C語言基礎函式C語言函式
- C語言函式呼叫棧C語言函式
- C語言函式傳遞指標引數的問題詳解C語言函式指標
- C語言 printf詳解C語言
- C語言#define詳解C語言
- Go語言Slice作為函式引數詳解Go函式
- C語言庫函式及示例C語言函式
- C語言函式sscanf()的用法C語言函式
- C語言qsort函式的使用C語言函式
- C#語言函式遞迴C#函式遞迴
- c語言運算子詳解C語言
- C語言函式指標與回撥用函式C語言函式指標
- C/C++語言精髓 *和&詳解C++
- C語言巨集和函式淺析C語言函式
- c語言快速排序(庫函式使用)C語言排序函式
- c語言學習筆記===函式C語言筆記函式
- C語言有關函式淺析C語言函式
- C語言指標詳解(一)C語言指標
- C語言指標詳解(二)C語言指標
- C語言-srand種子詳解C語言
- c語言函式指標的定義C語言函式指標
- C 語言實現泛型 swap 函式泛型函式
- 匿名函式(lambda)詳解 C++函式C++
- C語言函式指標與回撥函式使用方法C語言函式指標
- C語言可變引數詳解C語言
- Go 語言函式Go函式
- 瞭解 JavaScript 函數語言程式設計 - 宣告式函式JavaScript函數程式設計函式
- python函數語言程式設計詳解Python函數程式設計
- c語言是如何處理函式呼叫的?C語言函式
- C語言相關的基礎字串函式C語言字串函式
- 【C語言】函式的概念和函式的呼叫(引數傳遞)C語言函式
- c/c++語言函式 stat, fstat, lstat, fstatat - get file statusC++函式