C語言中的可變引數(printf的實現原理)

2021-08-20 23:28:15 字數 1002 閱讀 1211

printf是根據格式化的字元來確定的棧中引數的值,長度。

在c/c++中,對函式引數的掃瞄是從後向前的。c/c++的函式引數是通過壓入堆疊的方式來給函式傳引數的(堆疊是一種先進後出的資料結構),最先壓入的引數最後出來,在計算機的記憶體中,資料有2塊,一塊是堆,一塊是棧(函式引數及區域性變數在這裡),而棧是從記憶體的高位址向低位址生長的,控制生長的就是堆疊指標了,最先壓入的引數是在最上面,就是說在所有引數的最後面,最後壓入的引數在最下面,結構上看起來是第乙個,所以最後壓入的引數總是能夠被函式找到,因為它就在堆疊指標的上方。printf的第乙個被找到的引數就是那個字元指標,就是被雙引號括起來的那一部分,函式通過判斷字串裡控制引數的個數來判斷引數個數及資料型別,通過這些就可算出資料需要的堆疊指標的偏移量了,下面給出printf("%d,%d",a,b);(其中a、b都是int型的)的彙編**。

.section

.data

string out = "%d,%d"

push b //最後的先壓入棧中

push a //最先的後壓入棧中

push $out//引數控制的那個字串常量是最後被壓入的

call printf

你會看到,引數是最後的先壓入棧中,最先的後壓入棧中,引數控制的那個字串常量是最後被壓入的,所以這個常量總是能被找到的。

通常情況下函式可變參數列的長度是已知的,通過num引數傳入,這種函式比較容易實現。

而printf函式的實現非常複雜因為

1)可變引數的個數不能輕易的得到

2)而可變引數的型別也不是固定的,需由格式字串進行識別(由%f、%d、%s等確定)

在這個函式中,需通過對傳入的格式字串(首位址為lpstr)進行識別來獲知可變引數個數及各個可變引數的型別,具體實現體現在for迴圈中。譬如,在識別為%d後,做的是va_arg ( vap, int ),而獲知為%l和%lf後則進行的是va_arg ( vap, long )、va_arg ( vap, double )。格式字串識別完成後,可變引數也就處理完了。

c語言中可變引數的原理 printf 函式

函式原型 int printf const char format argument 返 回 值 成功則返回實際輸出的字元數,失敗返回 1.函式說明 在printf 函式中,format後面的引數個數不確定,且型別也不確定,這些引數都存放在棧內.呼叫printf 函式時,根據format裡的格式 d...

C語言中的可變引數

1 需要標頭檔案 include 2 函式定義 void logcmd int arg0,void logcmd char arg0,3 解析 i 數字型別 void logcmd int n,其中n表示引數的個數,n之後才是真正的引數。呼叫如 logcmd 0 logcmd 1,9 logcmd ...

C語言中可變引數的用法

c語言中可變引數的用法 我們在c語言程式設計中會遇到一些引數個數可變的函式,例如printf 這個函式,它的定義是這樣的 int printf const char format,它除了有乙個引數format固定以外,後面跟的引數的個數和型別是 可變的,例如我們可以有以下不同的呼叫方法 printf...