C++不定参实现

来源:互联网 发布:阿里云和腾讯云哪个好 编辑:程序博客网 时间:2024/06/05 11:14

 /********************************************************************
    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)     //将指针置为无效


0 0
原创粉丝点击