c語言學習之函數補漏

每次回頭看一些c的基礎知識,都有新感覺,覺得這個怎麼以前沒見到過,靠,這麼吊,這又是啥。零零碎碎的東西太多,腦子瞬間感覺不夠用啦。
一些基礎的就不在這囉嗦了,記錄一些不常用的點,以後再來看,不用再翻箱倒櫃的找了。

1.函數的缺省認定

這個主要提到函數原型的重要性,函數原型的作用就是讓編譯器知道函數的參數數量和類型,以及返回值類型。如果沒有原型,直接調用,編譯器是默認返回整型。
float f;
f = xyz();
在函數調用之前,編譯器沒能見到它的原型,便認定函數返回一個整型值。

2.函數的參數爲數組名時

c函數的參數都是以“傳值調用”方式來進行傳遞的。獲得參數值的一份拷貝。當傳遞的參數使數組名時,函數中使用下標對數組元素修改時,實際修改的是調用程序的數組元素。看似好像是進行的是“傳地址調用”,實際上,還是傳值調用,只不過拷貝的是指針,這個指針也能訪問內存中的位置。

3.函數的參數爲數組時,爲什麼要同時有長度參數

在聲明數組參數時不指定它的長度是合法的,因爲函數並不爲數組分配內存,而是訪問調用程序中的數組元素。但是函數沒用辦法判斷數組的長度,所以需要長度參數。
void clear_array( int array[],int length)

4.ADT(抽象數據類型)

就是限定用戶的訪問權限,隱藏具體的實現細節,用戶只能也只用調用那些已經定義好的接口。這些就是c++中的封裝特性。在c中主要通過關鍵字static來實現的,在函數之前加上static,這樣就只能本文件內調用了,具有內部鏈接屬性。

5.遞歸的討論

一直遞歸都是我的痛處,老是糾纏於它的執行過程,想幾個循環之後感覺就懵逼了。c和指針上的話說的很好:閱讀遞歸的方法就是要相信遞歸函數會順利完成任務。不要糾結於它的執行過程。如果你的限制條件正確,每個步驟正確,遞歸函數總是能正確完成任務。
c是通過運行時堆棧支持遞歸函數的實現。
遞歸原理:
當函數被調用時,它的變量的空間是創建於運行時的堆棧上的,如果在函數調用期間,又調用了其他的函數,則原理的變量仍保留在堆棧上,不過被新的函數的變量掩蓋。
對於遞歸函數,當調用自身的時候,每調用一次自己,將創建一批新的變量,將掩蓋遞歸函數前一次調用自己所創建的變量。當遞歸結束條件爲真時,依次返回函數。
書上將的還是很清楚的,以4267爲值調用遞歸函數,開始執行,堆棧的內容如圖這裏寫圖片描述
執行除法運算後:
這裏寫圖片描述
判斷條件非真,遞歸調用
這裏寫圖片描述
繼續判斷:
這裏寫圖片描述
現在quotient變爲零,遞歸函數不再調用自身,開始打印輸出。然後函數返回,開始銷燬堆棧上的變量值。
這裏寫圖片描述
這裏寫圖片描述
最後回到調用的起點。

遞歸的優點就是結構清晰,可讀性高。
當然遞歸不是萬能的,因爲遞歸不斷爲局部變量分配內存空間,開銷很大,而且有時候會重複計算,有時候簡單的循環或者迭代也會起到很好的效果。

6.可變參數列表

這個在實際中用的比較少,一般我們的參數個數和類型在原型中已經聲明好了,當時在項目中看到別人用到,感覺好神奇。但是感覺數組也能實現。
可變參數列表通過宏來實現的,stdarg.h ,它聲明瞭一個類型va_list和三個宏va_start ,va_arg,va_end。

/*計算指定數量的值的平均值*/
#include <stdarg.h>

float average(int n_values,...)
{
    va_list var;  //用於訪問參數列表中未確定的部分
    int count;
    float sum = 0;

    va_start(var,n_values);//初始化,第二個參數是省略號前最後一個參數。
    for(count =0;count < n_values ;count++)
        sum +=va_arg(var,int); //va_arg返回參數的值,將var指向下一個可變參數
    va_end(var);
    return sum/n_values;
}

缺點:
1,無法判斷實際存在的參數數量
2,無法判斷每個參數的類型,注意va_arg中使用類型

發佈了47 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章