筆者最近看《c與指標》這本書,發現了許多從前學習時沒有遇見的有趣問題。最讓筆者震驚的是第五章5.8習題中第二題,讓筆者又從頭認真學習了一遍c語言的static變數。
剛開始,筆者用一向的慣性思維思考這個問題。因此筆者自信地寫下了answer的值為 -2.
結果開啟vim 編輯之後,發現事情沒有這麼簡單。。。
是的,輸出的結果是 -10。 嗯??????
身為一位新時代的年輕人,不禁想問一句,「什麼鬼操作???」
不如吃茶去。。。
腦子一機靈,不如化簡?
不錯不錯,根據筆者的想法,將源**的主函式化為:
int answer;
int a = fun();
//printf("a %d\n", a);
int b = fun();
//printf("b %d\n", b);
//printf("mul %d\n", a*b);
answer= fun() - a * b;
printf("%d\n", answer);
vim 執行完之後結果,恰好是筆者寫的 -2 。當然,這個結果是完全錯誤的。。。
到底問題出在哪了呢?
那麼?答案不是 4-2*3 = -2 麼?不是,事情沒有那麼簡單。。。繼續繼續,我們認真觀察這一天語句:
必須要清楚的是,fun() 不是乙個變數,而是乙個返回值。fun() 函式位址是一定的,因此其實結果是 answer = 4 - 4*4 ,這樣結果就是 -10了麼。 是這樣麼???answer = fun() - fun() * fun() ;
想知道我們的推理是否正確,不如將 「-」 改為 「+」。因此我們將源**這條語句改為:如果按照我們的推理,得到的結果應該是20 才對。answer = fun() + fun() * fun() ;
14??? 不按常量出牌啊老鐵。
證明我們的想法是完全錯誤的。。。
不過,我們已經將函式的返回值與變數值之間的關係區分開了。這時看到《c與指標》上的一段話:什麼意思呢?
不如讓我們拋棄算數邏輯的先後順序。 從左向右執行下去。
這樣的話,我們再將得到的返回值進行邏輯運算。這樣我們就清楚了。answer = fun() - fun() * fun() ;
// 相當於 answer = 2 - 3 * 4 自然就是 -10
answer = fun() + fun() * fun();
// 相當於 answer = 2 + 3 * 4 自然就是 14
我們可以得到這麼一條結論:
當語句中存在函式時,會優先執行函式的操作,而後進行運算子的執行。其實這麼說有些果斷,片面。 因為當了解資料結構中,運算的實現原理之後,就會明白為什麼筆者現在會這麼說。 大致來說,運算的實現是又兩個「棧」實現的,乙個「運算子儲存棧」,乙個「變數儲存棧」。關於這個問題的具體詳解,筆者後面會講到。C 高階 C 函式呼叫過程深入分析
c 函式呼叫過程深入分析 0.引言 首先對三個常用的暫存器做一下說明,eip是指令指標,即指向下一條即將執行的指令的位址 ebp為基址指標,常用來指向棧底 esp為棧指標,常用來指向棧頂。看下面這個簡單的程式並在vc 6.0中檢視並分析彙編 1.函式呼叫 g func函式呼叫的彙編 如圖2 首先是三...
C 高階函式
函式式程式設計有很多優點,詳情可以參考我的博文 卡馬克 用c 進行函式式程式設計 在c 中,我們可以借助於函式物件或者函式指標來實現高階函式。高階函式是至少滿足下列乙個條件的函式 接受乙個或多個函式作為輸入 輸出乙個函式 公式 1 int sumint int a,int b for int i a...
(C )函式高階
include iostream using namespace std intfunc int a,int b 20,int c 30 1.如果某個位置已經有了預設引數,在這個引數之後都必須有預設引數 intfunc2 int a,int b 10,int c 10 b有預設引數,則c也需要有預設...