使用va_list+_vsnprintf处理不定参数

首先感觉这段代码挺实用的:

INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )    //这个技巧常用到
VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
VA_END宏,清空va_list可变参数列表:
#define va_end(ap) ( ap = (va_list)0 )
 
//其实va_start是将v后面的所有参数都放入ap这个va_list里了, 而va_arg不过获取下一个参数而已~
(详细去看百度百科)
 
其实本质上,利用的是:函数参数从右到左入栈的规则。测试代码:
void Test(int nCount, ...)
{
    cout<<"--------利用函数参数从右至左入栈的规则获取所有参数-------------"<<endl;

    int* nTmp = &nCount;
    cout<<"Hi, you have input "<<*nTmp<<"  arguments."<<endl;
    ++nTmp;

    cout<<"All other arguments are:"<<endl;
    for(int i = 0; i < nCount; ++i)
    {
        cout<<*nTmp<<"  ";
        ++nTmp;
    }

    cout<<endl<<endl;
}

Test(4, 11, 12, 13, 14);
int vsnprintf(char *str, size_t size,  const  char  *format,  va_list ap);  //Linux Edition: vsnprintf; Windows: _vsnprintf
测试代码:
/*test va_list 不定参数的使用方法*/
void Test__va_list(char* szFirstParam, ...)
{
    /*
    cout<<"--------利用函数参数从右至左入栈的规则获取所有参数-------------"<<endl;

    int* nTmp = &nCount;
    cout<<"Hi, you have input "<<*nTmp<<"  arguments."<<endl;
    ++nTmp;

    cout<<"All other arguments are:"<<endl;
    for(int i = 0; i < nCount; ++i)
    {
        cout<<*nTmp<<"  ";
        ++nTmp;
    }

    cout<<endl<<endl;
    */

    cout<<"---------利用封装的va_list获取所有参数------------"<<endl;

    va_list args;
    va_start(args, szFirstParam);
    char* chPara = NULL;

    while(1)
    {
        chPara = va_arg(args, char*);
        if(strcmp(chPara, "") == 0)
            break;
        cout<<chPara<<"  ";
    }
    va_end(args);
}



void MyFormat(char* szDest, int nSizeDest, char* szFormat, ...)  /*user is reponsible for the memory allocation and free of szDest and szFormat*/
{
    cout<<"----------测试将va_list和_vsnprintf结合起来----------"<<endl;
    va_list args;
    va_start(args, szFormat);
    _vsnprintf(szDest, nSizeDest, szFormat, args);
    va_end(args);
}

void Func21()
{
    Test__va_list("Demo:", "This", "Is", "A", "Demo!", "");
    
    cout<<endl;

    char szDest[50] = {0};
    MyFormat(szDest, 50-1, "Test:%d%s", 99, "Ninety-Nine");
    cout<<szDest<<endl;
}

测试结果:

---------利用封装的va_list获取所有参数------------
This  Is  A  Demo!
----------测试将va_list和_vsnprintf结合起来----------
Test:99Ninety-Nine

posted @ 2014-03-02 18:53  Tup  阅读(487)  评论(0)    收藏  举报