zoukankan      html  css  js  c++  java
  • 【转】C/C++中可变参数的详细介绍(va_list,va_start,va_arg,va_end)

      可变参数的函数原理其实很简单,而va系列是以宏定义来定义的,实现跟堆栈相关.我们写一个可变函数的C函数时,有利也有弊,所以在不必要的场合,我们无需用到可变参数。如果在C++里,我们应该利用C++的多态性来实现可变参数的功能,尽量避免用C语言的方式来实现。

      由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载。对这种情况,提出了指针参数来解决问题。

    如printf()函数,其原型为:
    int   printf(   const   char*   format,   ...);

    它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的,例如我们可以有以下不同的调用方法:  
    printf( "%d ",i);  
    printf( "%s ",s);  
    printf( "the   number   is   %d   ,string   is:%s ",   i,   s);

    如何实现其功能?

    我们需要以下几个宏定义:

    (1)va_list
    定义了一个指针arg_ptr, 用于指示可选的参数.

    (2)va_start(arg_ptr, argN)
    使 参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,argN是位于第一个可选参数之前的固定参数, 或者说最后一个固定参数.如有一va函数的声明是void va_test(char a, char b, char c, ...), 则它的固定参数依次是a,b,c, 最后一个固定参数argN为c, 因此就是va_start(arg_ptr, c).

    (3)va_arg(arg_ptr, type)
    返回参数列表中指针arg_ptr所指的参数, 返回类型为type. 并使指针arg_ptr指向参数列表中下一个参数.返回的是可选参数, 不包括固定参数.

    (4)va_end(arg_ptr)
    清空参数列表, 并置参数指针arg_ptr无效.

    (注:va在这里是variable-argument(可变参数)的意思.   这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件)

    也需你现在还是不能理解,别着急,现在从一个实例着手.定义这么一个函数,函数的第一个参数是固定的,其余参数是可变的。定义为:
    void   simple_va_fun(int i,...); 其代码为:

    #include <iostream>
    #include <string>
    #include <iostream>
    using namespace std;
    #include <stdarg.h>
    void simple_va_fun(int i, ...)
    {
        va_list arg_ptr;       /// 定义可变参数指针
        va_start(arg_ptr, i);  /// i为最后一个固定参数
        int j = va_arg(arg_ptr, int); //返回第一个可变参数,类型为int
        char c = va_arg(arg_ptr, char); ///返回第二个可变参数,类型为char
        va_end(arg_ptr);  ///清空参数指针
        printf("%d %d %c", i, j, c);
        return;
    }
    
    int main()
    {
        simple_va_fun(100);
        cout << endl;
        simple_va_fun(100, 200);
        cout << endl;
        simple_va_fun(100, 200, 'a');
        cout << endl;
        system("pause");
        return 0;
    }
  • 相关阅读:
    进入MFC讲坛的前言(四)
    进入MFC讲坛的前言(二)
    进入MFC讲坛的前言(一)
    进入MFC讲坛的前言(三)
    jar命令+7z:创建,替换,修改,删除Jar, war, ear包中的文件
    java架构之项目结构(entity / DTO / VO)
    面试无忧之Zookeeper总结心得
    BigDecimal.setScale 处理java小数点
    最详细的 paypal 支付接口开发--Java版
    社会化登录分享-Android SDK的二次封装和使用
  • 原文地址:https://www.cnblogs.com/yongssu/p/4677556.html
Copyright © 2011-2022 走看看