C/C++中处理可变长参数的库函数-----va_start()、va_arg()、va_end()

下面介绍一套处理函数变长参数的库函数
linux中的program手册对这一套函数有如下的描述:
一个函数被调用的时候,也许会给与数量和类型都不确定的实参。
在头文件

void va_start(va_list ap, last);
    描述:va_start这个宏将参数 ap初始化,以便后续提供给va_arg()和va_end()这两个宏使用。
    参数:
    ap:用于存放可变参数的链表
    last:可变参数链表前的最后一个参数的名字。其他函数调用这个函数的时候,在填写可变实参前的最后一个实参。
    注释:这个参数不可以是寄存器类型,函数类型或者数组类型。
    返回值:无
----------
    type va_arg(va_list ap, type);
    描述:va_arg()这个宏扩展成了一个表达式。调用它可以获得下一个参数的类型和值。
    参数:
    ap:被va_start()宏初始化过的参数链表。每次调用va_arg()这个宏的时候,都会改变ap所代表的链表,所以每次调用va_arg()都会返回下一个参数的类型和值。
    type:一个被指定的类型名称。通过对这个类型名称加 * 运算符就可以得到指向这个对象的指针。(这句话没什么特别的意思,就是说实参是个指针的话,那么type也要指定成对应类型的指针,才能正确的拿到参数)
    返回值:指定类型
    在va_start()宏返回之后,第一次使用va_arg()宏,将会返回last参数之后的参数。连续成功调用,会返回其余的参数。
    如果没有下一个参数了,或者指定的type和链表中实际的参数类型不同,会发生随机的错误。
    如果参数ap被传递给其他函数使用,在函数返回之后,这个ap会变成未知的状态。
----------
void va_end(va_list ap);
    描述:每次调用va_start()宏之后,必须调用va_end()。调用va_end()函数之后,ap这个参数的内容会变成未知状态。一个函数中,可以多次遍历其参数链表,每次遍历都必须使用va_start()和va_end()包起来。
    返回值:无
----------
void va_copy(va_list dest, va_list src);
    描述:在va_start()之后,将一个参数链表复制到另一个参数链表,这个行为类似于,再对一个ap参数进行va_start()的调用。
    参数:
    dest:目标参数链表
    src:源参数链表
    返回值:无
    注释:再va_copy()之后,也需要调用va_end(),去正常结束。

以下为上述函数的演示代码及其结果

#include <iostream>
#include <stdarg.h>
using namespace std;
void print(const char *args,...){
        va_list ap;
        va_list aq;
        va_start(ap,args);
        va_copy(aq,ap);
        char *arg = NULL;
        while(NULL != (arg = va_arg(ap,char *))){
                cout << arg << endl;
        }
        va_end(ap);
        while(NULL != (arg = va_arg(aq,char *))){
                cout << arg << endl;
        }
        va_end(aq);
        return;
}
int main(void){
        print("1","Hello","World",NULL);
        return 0;
}
----------
Hello
World
Hello
World

猜你喜欢

转载自blog.csdn.net/displaymessage/article/details/80874276