zoukankan      html  css  js  c++  java
  • C/C++中带可变参数的函数

    1.带可变参数的函数由来

    函数中的参数个数不确定时,这时候就需要带可变参数的函数!

    如我们经常使用的C库函数printf()实际就是一个可变参数的函数,

    其原型为:

     
     int   printf(   const   char*   format,   ...);

    它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的。例如我们可以有以下不同的调用方法:

    printf( "%d ",i);   
    printf( "%s ",s);   
    printf( "the   number   is   %d   ,string   is:%s ",   i,   s);   

    2.带可变参数函数的实现,

    原理:

    • 使用了指针参数来解决参数的可变问题,指针参数随着其移动指向不同的参数;
    • C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数。

    C语言标准库中头文件stdarg.h索引的接口包含了一组能够遍历变长参数列表的宏。

    头文件

    #include <stdarg.h>
    

    几个宏

    (1).  va_list  定义一个指针

    用来定义一个表示参数表中各个参数变量,即定义了一个指向参数的指针, 用于指示可选的参数.

    如:va_list ap;

    (2). va_start(ap,v)  初始化指针  

    使参数列表指针ap指向函数参数列表中的第一个可选参数v是位于第一个可选参数之前的固定参数, 或者说最后一个固定参数.通常用于指定可变参数列表中参数的个数!

    如有一va函数的声明是void va_test(char a, char b, char c, ...), 则它的固定参数依次是a,b,c, 最后一个固定参数v为c, 因此就是va_start(ap, c).

    
    

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

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

    例:

    #include <iostream>
    #include <stdarg.h>
    using namespace std;
    void simple_va_fun(int i,...);
    
    int main(int argc,char *argv[])
    {
        simple_va_fun(100);   
        simple_va_fun(100,200);
        simple_va_fun(100,200,'a');
        return 0;
    }
    
    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;   
    }
    /*

    输出为

    
    

    100 4193388 ?
    100 200 ?
    100 200 a

    */

     

     思路:

    (1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针.

    (2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.

    (3)然后用va_arg返回第一个可变的参数,并赋值给整数j。va_arg的第二个参数是你要返回的参数的类型,这里是int型.  返回第一个可变参数后arg_ptr指向第二个可变参数,用同样的方法返回并赋值给c,类型为char类型。

    (4)最后用va_end宏结束可变参数的获取。

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

    参考

    http://www.jb51.net/article/41868.htm

  • 相关阅读:
    Oracle自增ID实现
    mysql5修改用户密码及远程访问
    关于线程中修改UI的控件属性
    Javascript 保持浮动位置
    Linq To Entity 查询条件扩展
    反转字符顺序
    VB6.0 二分法解方程
    支持库:FileHelper
    C# 计算加减乘除
    Linq.GroupBy使用示例
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/8781915.html
Copyright © 2011-2022 走看看