不定長引數函式的實現

2021-06-06 13:33:51 字數 1786 閱讀 4964

原始碼如下:

int sum(int num, ...)

return ret;

}int main(int argc, char* argv)

所謂不定長引數,就是函式的形參數量不定,型別也可能是不定的。我們把像上面的函式sum中如「int num」這樣的引數叫做「有名引數」,後面用「…」代表的都是「匿名引數」,有名引數是可以在函式中通過變數名直接訪問的,匿名函式則無法通過變數名直接訪問,只能是通過相對有名引數的位置(位址)來訪問了。

關鍵在於:

(1)匿名引數的個數和型別必須通過有名引數傳遞給被調函式

如printf中的第乙個引數「const char *fomat」,在format中不僅告訴了printf引數的個數,還必須指定正確的型別,二者缺一不可。

(2)被調函式本身有辦法直接或間接定位引數的個數和型別

即描述引數個數和型別的引數的位置應該是固定的,函式有辦法定位它們,而不是如匿名引數那般不確定的。像c語言的標準呼叫方式,即從右至左壓棧且呼叫方清理棧的方式是比較合適的,尤其是前者,如果在第乙個引數中指定各引數的個數和格式,則根據棧的規律可以知道,返回位址上方即是第乙個引數(即ebp+8),以後的匿名引數則可依次確定了。

上面原始碼中的sum彙編**如下:

7:        int *p = &num + 1;

00401038   lea         eax,[ebp+0ch]

0040103b   mov         dword ptr [ebp-4],eax

8:        int ret = 0;

0040103e   mov         dword ptr [ebp-8],0

9:        while(num--)

00401045   mov         ecx,dword ptr [ebp+8]

00401048   mov         edx,dword ptr [ebp+8]

0040104b   sub         edx,1

0040104e   mov         dword ptr [ebp+8],edx

00401051   test        ecx,ecx

00401053   je          sum+5ch (0040107c)

10:      

0040107a   jmp         sum+25h (00401045)

14:       return ret;

0040107c   mov         eax,dword ptr [ebp-8]

15:   }

由此又可以進一步驗證兩個問題:

(1)指標的運算。

指標的加減都是以型別的大小為乙個單位的,無論是p = &num+1(相當於加4),還是*p++(先計算*p,在執行p++,相當於加4)

如此,若我真的要將位址加1而非加乙個資料單位,又當如何呢?

答案是只能先將&num轉換成單位元組變數指標,如(char *)&num

這種做法其實還是遵循著指標的加減1是資料單位的加減1,只不過是上述做法,將資料單位強制轉換成了1byte而已。

(2)while(num--)的執行

這個過程看上去有點兒古怪,先是把num的值儲存到了乙個臨時變數(暫存器ecx)中,然後執行num--,但是判斷與0的關係的時候,用的又不是num的值,而是臨時變數ecx中儲存的num原值。這是我始料不及的。

這也就是為什麼明明num已經為0了,while還可以執行一次的原因,因為用來做判斷的那個值始終比num的實際值要大一號:p

所有的都記錄下來備查吧:p

不定長引數

不定長引數 在定義函式時,不確定接收引數的個數,此時可以使用不定長引數 不定長引數的表現形式 1.args 表示在呼叫函式時,專門來負責接收不確定個數的位置引數的。2.kwargs 表示在呼叫函式時,專門來負責接收不確定個數的關鍵字引數的。當呼叫函式時,會把所有的關鍵字引數打包到乙個字典裡面,然後把...

不定長引數方法

package com public class unfixedparameter testone new string testtwo testtwo a b c public static void testone string args public static void testtwo s...

Python不定長引數

記錄了python函式的不定長引數,用 來接收不定長的資料。在定義函式時,可以在形參前邊加上乙個 這樣這個形參將會獲取到所有的實參,它將會將所有的實參儲存到乙個元組中 a會接受所有的位置實參,並且會將這些實參統一儲存到乙個元組中 裝包 fn3函式的使用 形參可以接收其他的關鍵字引數,它會將這些引數統...