c語言中關於可變參數的研究

#include <stdio.h>
#include <stdarg.h>

void PrintLines(char *first,...)
{
    char *str;

    va_list v1;
    str = first;

    va_start(v1,first);
    do 
    {
        printf("%s\n",str);
        str = va_arg( v1 , char* );
    } while (str != NULL );
    va_end(v1);
}

int main(int argc, char* argv[])
{
    PrintLines("First","Second","Third","Fourth",NULL);
    return 0;
}

函數如何定義可變參數

//eg:
void PrintLines(char *first,...);
//用三個點來代表可變參數

函數如何接受處理可變參數
使用 va_list va_start va_end va_arg
那他們究竟是什麼呢

typedef char *  va_list;
#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end

繼續(我的測試平臺:win32,x86,c文件)

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )


#ifdef  __cplusplus
#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
#else
#define _ADDRESSOF(v)   ( &(v) )
#endif


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

所以 va_list 本質上是 char *,v1存儲的的是參數first的內存地址

 v1 = (char *)_ADDRESSOF(first) + _INTSIZEOF(first) 

而 va_arg 則可以不斷根據類型向後遍歷變量,因爲參數棧本身是不會標明參數個數的,所以我們要在調用函數的時候,表明確定參數個數的方法,比如printf中的fmt,或者在函數的第一個參數處指明參數個數,或者最後一個變量設置爲NULL等等。
最後使用va_end將指針清空。

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章