函数参数深度剖析
文章目錄
- 1 函數(shù)參數(shù)的本質(zhì)
- 1.1 函數(shù)參數(shù)的本質(zhì)
- 2 函數(shù)參數(shù)的求值順序
- 2.1 順序點(diǎn)的概念
- 2.2 函數(shù)參數(shù)的求值順序分析
- 3 函數(shù)參數(shù)的入棧順序
- 3.1 調(diào)用約定
1 函數(shù)參數(shù)的本質(zhì)
1.1 函數(shù)參數(shù)的本質(zhì)
函數(shù)參數(shù)的本質(zhì)如下:
- 函數(shù)參數(shù)在本質(zhì)上與局部變量相同在棧上分配空間。
- 函數(shù)參數(shù)的初始值是函數(shù)調(diào)用時的實(shí)參值。
2 函數(shù)參數(shù)的求值順序
2.1 順序點(diǎn)的概念
順序點(diǎn)是C語言中變量修改的最晚時機(jī)。
程序中的順序點(diǎn):
- 程序中存在一定的順序點(diǎn)。
- 順序點(diǎn)指的是執(zhí)行過程中修改變量值的最晚時刻。
- 在程序到達(dá)順序點(diǎn)的時候,之前所做的一切內(nèi)存操作必須完成。
C語言中的順序點(diǎn):
- 每個完整表達(dá)式結(jié)束時,即分號處。
- &&,||,?:以及逗號表達(dá)式的每個參數(shù)計(jì)算后。
- 函數(shù)調(diào)用時所有實(shí)參求值完成后(進(jìn)入函數(shù)體之前)。
輸出結(jié)果:6(gcc、bcc、vc)
分析:首先將k的值取道寄存器中去,然后再從內(nèi)存中把k的值取出來和寄存器中的值進(jìn)行相加,將值保存到k中去,此時懸掛了兩個++操作。然后進(jìn)行兩次++操作,所以此時的k為6。
2.2 函數(shù)參數(shù)的求值順序分析
函數(shù)參數(shù)的求值順序依賴于編譯器的實(shí)現(xiàn)。
gcc: 2 1 3(最后一個為k的值)
bcc:2 1 3
vc: 1 1 3(跟順序點(diǎn)有關(guān),假設(shè)從第二個參數(shù)開始求值,首先從內(nèi)存中取出k的值為1,此時的++操作并沒有進(jìn),而是處于懸掛狀態(tài),所以第二個參數(shù)的值為1。然后對第一個參數(shù)進(jìn)行求值,從內(nèi)存中取出k的值為1,++操作仍然懸掛著,所以此時第一個參數(shù)的值也為1。由于順序點(diǎn)存在于函數(shù)調(diào)用時所有實(shí)參求值完成后,即進(jìn)入函數(shù)體前,所以此時必須進(jìn)行修改內(nèi)存的操作,執(zhí)行兩個++操作,使得此時的k的值變成了3)。
注意:C語言中只規(guī)定了必須將參數(shù)的值計(jì)算出來再進(jìn)行函數(shù)調(diào)用,并沒有規(guī)定參數(shù)的求值順序。可類比到操作符中,操作符的求值順序也是不固定的,依賴于編譯器的實(shí)現(xiàn)。
3 函數(shù)參數(shù)的入棧順序
3.1 調(diào)用約定
當(dāng)函數(shù)調(diào)用發(fā)生時:
- 參數(shù)會傳遞給被調(diào)用的函數(shù)。
- 而返回值會被返回給函數(shù)調(diào)用者。
調(diào)用約定描述參數(shù)如何傳遞到棧中以及棧的維護(hù)方式:
- 參數(shù)傳遞順序。
- 調(diào)用棧清理。
當(dāng)主函數(shù)調(diào)用第三方庫時,需要考慮調(diào)用約定是否一致。
關(guān)于調(diào)用約定:
- 調(diào)用約定是預(yù)定義的,可理解為調(diào)用協(xié)議。
- 調(diào)用約定通常用于庫調(diào)用和庫開發(fā)的時候:
- 從右到左依次入棧:_stdcall,_cdecl(C語言默認(rèn)是這個),_thiscall;
- 從左到右依次入棧:_pascal, _fastcall。
參考資料:
總結(jié)
- 上一篇: C和C++中的野指针问题
- 下一篇: 函数中的可变参数