可變引數與引數進棧順序

2021-06-16 11:27:36 字數 1182 閱讀 1534

c支援可變引數的函式,這裡的意思是

c支援函式帶有可變數量的引數,最常見的例子就是我們十分熟悉的

printf()

系列函式。我們還知道在函式呼叫時引數是自右向左壓棧的。如果可變引數函式的一般形式是:

f(p1, p2, p3, …)

那麼引數進棧(以及出棧)的順序是:

push p3

push p2

push p1

call f

pop p1

pop p2

pop p3

我可以得到這樣乙個結論:如果支援可變引數的函式,那麼引數進棧的順序幾乎必然是自右向左的。並且,引數出棧也不能由函式自己完成,而應該由呼叫者完成。

這個結論的後半部分是不難理解的,因為函式自身不知道呼叫者傳入了多少引數,但是呼叫者知道,所以呼叫者應該負責將所有引數出棧。

在可變引數函式的一般形式中,左邊是已經確定的引數,右邊省略號代表未知引數部分。對於已經確定的引數,它在棧上的位置也必須是確定的。否則意味著已經確定的引數是不能定位和找到的,這樣是無法保證函式正確執行的。衡量引數在棧上的位置,就是離開確切的函式呼叫點(call f

)有多遠。已經確定的引數,它在棧上的位置,不應該依賴引數的具體數量,因為引數的數量是未知的!

所以,選擇只能是,已經確定的引數,離開函式呼叫點有確定的距離(較近)。滿足這個條件,只有引數入棧遵從自右向左規則。也就是說,左邊確定的引數後入棧,離函式呼叫點有確定的距離(最左邊的引數最後入棧,離函式呼叫點最近)。

這樣,當函式開始執行後,它能找到所有已經確定的引數。根據函式自己的邏輯,它負責尋找和解釋後面可變的引數(在離開呼叫點較遠的地方),通常這依賴於已經確定的引數的值(典型的如prinf()

函式的格式解釋,遺憾的是這樣的方式具有脆弱性)。

據說在pascal

中引數是自左向右壓棧的,與

c的相反。對於

pascal

這種只支援固定引數函式的語言,它沒有可變引數帶來的問題。因此,它選擇哪種引數進棧方式都是可以的。甚至,其引數出棧是由函式自己完成的,而不是呼叫者,因為函式的引數的型別和數量是完全已知的。這種方式比採用

c的方式的效率更好,因為占用更少的**量(在

c中,函式每次呼叫的地方,都生成了引數出棧**)。

c++為了相容

c,所以仍然支援函式帶有可變的引數。但是在

c++中更好的選擇常常是函式過載。

C 特性探尋 可變引數和引數進棧順序

c支援可變引數的函式,這裡的意思是c支援函式帶有可變數量的引數,最常見的例子就 是我們十分熟悉的printf 系列函式。我們還知道在函式呼叫時引數是自右向左壓棧的 如果可變引數函式的一般形式是 f p1,p2,p3,那麼引數進棧 以及出棧 的順序是 push p3 push p2 push p1 c...

可變引數列印 解析可變引數

1.的一般用法 define str s s define cons a,b int a e b int main 2.接受,列印可變引數 參考 glibc庫的bebug函式 define printf fmt,args.printf fmt,args 使用方法 define pr debug fm...

預設引數,命名引數,可變引數

def sayname name string pk unit sayname 其中預設引數為pk,所以此時輸出pk sayname dog 此時傳入引數dog,那麼就以你當前傳入的引數為準,輸出dogdef speed distance float time float float println...