C++不定參實現

 /********************************************************************
    purpose: 可變參測試    
    author:  dotlive    
*********************************************************************/
#include <stdio.h>
#include <stdarg.h>

const int INT_TYPE        = 100000;
const int STR_TYPE        = 100001;
const int CHAR_TYPE        = 100002;
const int LONG_TYPE        = 100003;
const int FLOAT_TYPE    = 100004;
const int DOUBLE_TYPE    = 100005;

//測試va_start,va_arg的使用方法,函數參數在堆棧中的地址分佈情況
void arg_test(int i, ...);
//第一個參數定義可選參數個數,用於循環取初參數內容
void arg_cnt(int cnt, ...);
//可變參數採用arg_type,arg_value...的形式傳遞,以處理不同的可變參數類型
void arg_type(int cnt, ...);

int main(int argc, char *argv[]) 
{
    int int_size = _INTSIZEOF(int);
    printf("int_size = %d\n", int_size);

    printf("\nThis is arg_test's result:\n");
    arg_test(0, 4);
    printf("\nThis is arg_cnt's result:\n");
    arg_cnt(4, 1, 2, 3 ,4);
    printf("\nThis is arg_type's result:\n");
    arg_type(2, INT_TYPE,222/*arg1*/, STR_TYPE,"ok,hello world!"/*arg2*/);
    printf("\n");

    return 0;
}

void arg_test(int i, ...)
{
    int j = 0;  
    va_list arg_ptr;  

    va_start(arg_ptr, i);
    //打印參數i在堆棧中的地址
    printf("&i = %p\n", &i);
    //打印va_start之後arg_ptr地址。應該比參數i的地址高sizeof(int)個字節, 這時arg_ptr指向下一個參數的地址
    printf("arg_ptr = %p\n", arg_ptr);

    j = *((int*)arg_ptr);
    printf("%d %d\n", i, j);  
    j = va_arg(arg_ptr, int);  
    //打印va_arg後arg_ptr的地址。應該比調用va_arg前高sizeof(int)個字節, 這時arg_ptr指向下一個參數的地址
    printf("arg_ptr = %p\n", arg_ptr);
    va_end(arg_ptr);  
    printf("%d %d\n", i, j);  
}

void arg_cnt(int cnt, ...)
{
    int i = 0;
    int arg_cnt = cnt;  
    int value = 0;  
    va_list arg_ptr;

    va_start(arg_ptr, cnt);  
    for(i = 0; i < arg_cnt; i++)
    {
        value = va_arg(arg_ptr,int);
        printf("value%d = %d\n", i+1, value);
    }
}

void arg_type(int cnt, ...)
{
    int i = 0;
    int arg_cnt = cnt;  
    int arg_type = 0;
    int int_value = 0;  
    char *str_value = NULL;
    va_list arg_ptr;

    va_start(arg_ptr, cnt);  
    for(i = 0; i < arg_cnt; i++)
    {
        arg_type = va_arg(arg_ptr, int);
        switch(arg_type)
        {
        case INT_TYPE:
            int_value = va_arg(arg_ptr, int);
            printf("value%d = %d\n", i+1, int_value);
            break;
        case STR_TYPE:
            str_value = va_arg(arg_ptr, char*);
            printf("value%d = %s\n", i+1, str_value);
            break;
        default:
            break;
        }
    }
}

其中,在VC的庫文件中有一個stdarg.h頭文件,有如下幾個宏定義:

#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)     //將指針置爲無效


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章