遞迴使用,潛在問題

2021-06-16 01:07:27 字數 1866 閱讀 8203

題記:

本篇文章由乙個「有問題」的程式,帶入你進入遞迴的世界。雖然只是採用了遞迴中最簡單的型別,尾遞迴。但卻能使你馬上感受到遞迴的妙用和煩惱。希望大家由淺入深、循序漸進,更好的使用遞迴。其中又涉及了遞減運算子的使用,它同樣是讓你歡喜讓你憂!雖然使用它給你帶來高效的**,但不小心同樣讓你深陷泥潭。

1.#include

2.long fun(int );

3.int i=1,j=3;

//i,j

僅僅是為了說明遞迴時是第幾級呼叫

4.5.int main(void)

6.12.

13.long fun(int m)

14.38.else

39.42.return ans;

43.}

嘗試分析

5個可測選項會輸出什麼結果?

#1正確,依次呼叫、返回。最終效果為:

fun(0)*5*4*3*2*1

#2/3/4

表示式雖略有差異,但***相同,動作發生時間相同。

貌似可以產生正確結果但執行卻發現「

n=0」,

why?發生了什麼?這就要從遞迴的原理考慮,並對比

#1的形式。如果是

#1,在一級呼叫

fun時

(main

對fun

的呼叫)

,即fun(3),

然後這個函式呼叫還沒執行完,就執行了

fun(2)

『自身呼叫,

fun對

fun,和

#1一樣,但同時它把

m的值改變了!』

… 效果如上文所示

如果採用

#2的形式,效果:

fun(0)*4*3*2*1*0

,所以「

n=0」

#5是最複雜的,同時難於理解,最好能了解遞迴的細節、副操作、順序點等知識

(在文章最後,有簡略解釋)。

一級呼叫

fun(),

即fun(3),

注意傳遞給

fun函式時,m就是

3,而二級呼叫(呼叫自身)時,

m的值還沒改變呢

(字尾遞減

)!又是

fun(3)

。**呼叫也將是

fun(3)……

遞迴雖然有條件檢測語句

(17行

)用於結束遞迴,但

m值相當於不變,一直遞迴,知道資源耗竭為止!

是否有疑問呢?為什麼要說「相當於」呢?如果你夠細心,肯定發現了一點蛛絲馬跡!

m值其實變了,但什麼時候變了?以二級呼叫為例解釋,即第一次自身呼叫時。

fun函式呼叫時

m給了它,隨後

m變成了,這可以通過加入22、

23行**加以驗證,你會發現

m確實變成了

2。那**呼叫不就是

fun(2)

了嗎?不是!!

遞迴是個很奇妙的東西!它總能迷惑你的雙眼。

每一級函式呼叫都有自己的變數!此m

非彼m,可以從位址中發現(我在這個例項已經加入了顯示位址的語句)。

如果兩個不同的函式,可能我們很容易的就明白,兩個

m的不同

如:fun1(int m)

fun2(int m)

但換到遞迴,我們可能就摸不到頭緒了。在此建議大家:

多聯絡多思考,語言是由基本要素擴充擴充套件而來。

如遞迴不過是函式呼叫自身,那麼函式具有的特性,它也應該具有!

遞減運算子在這個程式給你帶來的

trouble

夠大嗎?所以用之勿慎!

c就是這樣,夠靈活以致可以夠高效、夠強大;靈活又使我們摔倒千次。

決定命運的關鍵

立即行動

php fpm backlog引數潛在問題

前幾天有業務在新機器上線測試時,發現個問題 同樣的資源的虛機 同樣配置的ngxin php fpmweb後端的兩台機器,測試後發現 訪問.html檔案時qps相差不大,但是訪問php 頁面時其中一台的qps是另一台的數倍。通過分析,發現是php fpm的backlog引數引起的,可以通過設定php ...

日期格式化使用 YYYY MM dd 的潛在問題

昨天在v站上看到這個關於yyyy mm dd的使用而出現bug的帖子 v2ex.com t 633650 非常有意思,所以拿過來分享一下。在任何程式語言中,對於時間 數字等資料上,都存在很多類似這種平時一切ok,特定時間 特定環境出問題的情況。出現這種問題的根本原因還是我們對於各種資料結構的細節定義...

c 混合使用不同標準編譯潛在的問題

最近專案使用的c 的版本到c 11了,但是由於有些靜態庫 a 沒有原始碼,因此鏈結時還在使用非c 11版本的庫檔案。目前跑了幾天,似乎是沒出什麼問題,但是我還是想說一下這樣做有哪些潛在的風險。首先需要說明的是,公升級到c 11之後,部分std的資料結構的記憶體布局有可能發生改變 待考究 最開始,我認...