C語言可變引數實現

2021-09-07 21:14:11 字數 1835 閱讀 8071

第一:什麼是可變引數

int printf(const char* format, ...);

看到printf的定義大家就知道了,只有乙個固定的const char*引數,後面的都是不定長的引數列表了。

第二:自己寫乙個可變引數函式

1.引數形參方式,跟printf類似,第乙個為固定引數,後面的用...代替;

2.包含stdarg.h標頭檔案,因為需要用到幾個裡面定義的巨集;

void va_start(va_list arg_ptr, prev_param);

type va_arg(va_list arg_ptr, type);

void va_end(va_list arg_ptr);

va是variable argument可變引數的意思。

3.函式裡面定義乙個va_list型別的變數,它是儲存引數位址的指標,因為得到引數的位址之後,再結合引數的型別,才能得到引數的值。

4.用va_start巨集初始化3中定義的va_list型別變數,

5.用va_arg巨集獲得下乙個引數的值

6.設定結束條件。

例子程式:

1#include

2#include//required by variable argument list

34void ******_va_function(int start, )while(nar**alue != -1);

14 va_end(arg_ptr);

15 return;

16}17

18int main()

第三:可變引數的編譯器實現原理,這幾個巨集的實現。

首先列出stdarg.h裡面的巨集定義(注意這個巨集定義與硬體平台和編譯器有關,這裡是vc6的巨集定義):

typedef char * va_list;

#define _intsizeof(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _intsizeof(v) )

#define va_arg(ap,t) ( *(t *)((ap += _intsizeof(t)) - _intsizeof(t)) )

#define va_end(ap) ( ap = (va_list)0 )

其中va_list被定為一般指標,有些機器使用void*,有些使用char*,反正都可以啦。

_intszeof(n)是考慮了記憶體對齊後的變數占用空間,自己考慮一下,代進去小於4位元組的型別進去算一下,就知道在這個平台上(32位機),記憶體對齊到4個位元組。

va_start就是求得第乙個可變引數的位址

va_end只是簡單地將指標置零

第四:小結

1.標準c庫的中的三個巨集的作用只是用來確定可變引數列表中每個引數的記憶體位址,編譯器是不知道引數的實際數目的。

2.在實際應用的**中,程式設計師必須自己考慮確定引數數目的辦法

1)在固定引數設定標誌,例如printf的實現,有多少個%號則表明後面多少個引數

2)多設定乙個可變引數標識引數列表結束

3.實現可變引數的要點就是想辦法取得每個引數的位址,取得位址的辦法由以下幾個因素決定:

①函式棧的生長方向

②引數的入棧順序

③cpu的對齊方式

④記憶體位址的表達方式,用void*表示一般位址還是char*

結合源**,我們可以看出va_list的實現是由④決定的,_intsizeof(n)的引入則是由③決定的,他和①②又一起決定了va_start的實現,最後va_end的存在則是良好程式設計風格的體現,將不再使用的指標設為null,這樣可以防止以後的誤操作。

C語言怎麼實現可變引數?

摘要 c語言使用可變引數,需要借助巨集。這些巨集定義在stdarg.件。stdarg.h宣告了乙個型別va list和三個巨集va start,va arg,va end。include va list v arg 定義乙個型別 va start v arg,len 引數列表初始化 va arg v...

c語言可變引數實現示例

這段 展示了如何不使用中的va list va start va end巨集來實現自定www.cppcns.com義可變引數以及如何改變預設的 d f s等格式字元。複製 如下 include include itoa and ltoa include strcat and strlen echo ...

c 語言可變引數

1 當無法列出傳遞函式的所有實參的型別和數目時,可用省略號指定參數列 void foo void foo parm list,2 函式引數的傳遞原理 函式引數是以資料結構 棧的形式訪問,從右至左入棧.eg include void fun int a,int main output 12 343 獲...