zoukankan      html  css  js  c++  java
  • [C]va_list可变长参数的使用

    一、概述

    运用标准C的头文件stdarg.h提供的宏可以实现函数的自定义传参个数;

    二、语法

    1.va_list是一个可变长参数类型,在使用可变长参数的函数中可以定义1个或多个va_list类型参数,等待va_start初始化后使用;

    va_list parg_1;
    va_list parg_2;

    2.va_start作用是给va_list类型变量绑定一个起始值

    宏原型:

    void va_start(va_list ap, last);

    ap是va_list类型变量;

    last是函数的最后一个固定参数(由于可变长函数的声明语法,参数部分必须至少包含一个固定传参);

    va_start执行后,该ap的指针将会指向变参的起始位置;

    3.va_copy作用是复制一份初始化后的va_list变量,通常用在调用va_start之后;

    void va_copy(va_list ap2, va_list ap1);

    ap2是复制到达的va_list变量;

    ap1是被复制的va_list变量;

    复制完毕后,两个变量的变长参数偏移量不相干;

    4.va_arg被调用后将会返回当前指针偏移量的参数,随之指针将会移动到下一个变参的位置

    type va_arg(va_list ap, type);

    ap是被初始化后的va_list变量;

    type是,除以下类型之外的其他类型

    type绝对不能为以下类型:
    ——charsigned char、unsigned char
    ——short、unsigned short
    ——signed shortshort int、signed short int、unsigned short int
    ——float

    这是因为C标准中有一个默认参数提升(default argument promotions)规则

    注意:有时候因为代码问题(例如类型错误)导致va_arg返回了错误的结果,但是也不会影响va_arg的下一次取参哦,这是因为指针的偏移是通过变参的底层size属性获取的

    5.va_end用于结束整个取参流程

    void va_end(va_list ap);

    二、示例

    1.通过代码说明printf的原理

    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    
    void myPrintf(const char *format, ...);
     
    int main(void)
    {
        char str_1[] = "January & February";
        double d_1 = 0.25;
        int i_1 = 16;
        char str_2[] = "March & April";
        int i_2 = 528;
        myPrintf(str_1, d_1, i_1, str_2, i_2);
    }
    
    void myPrintf(const char *format, ...)
    {
        printf("%s
    ", format);
        va_list parg;
        va_start(parg, format);
        printf("%.6lf
    ", va_arg(parg, double));
        printf("%d
    ", va_arg(parg, int));
        printf("%s
    ", va_arg(parg, char*));
        printf("%d
    ", va_arg(parg, int));
        va_end(parg);
    }

    输出:

    0.250000

    16

    March & April

    528

    说明:

    C自带的printf函数是根据第一个参数format的占位符解析出后面的变参个数和类型,通过va_arg迭代去获取变参再填充到占位符上输出。解析占位符并不是一件简单的工作,所以这里的代码只是大致说明了一下它的原理;

    2.求平均数

    #include <stdio.h>
    #include <stdarg.h>
    
    
    double average(double v1, double v2, ...);
    
    int count = 0;
    
    int main(void)
    {
        printf("Average = %.6lf
    ", average(0.2, 3.5, 108.625, (double)56, 0.3, 0.0));
    }
    
    double average(double v1, double v2, ...)
    {
        va_list parg;
        double sum = v1 + v2;
        double value = 0.0;
        int count = 2;
    
        va_start(parg, v2);
        while((value = va_arg(parg, double)) != 0.0)
        {
            printf("Item = %.6lf
    ", value);
            sum += value;
            ++count;
        }
        va_end(parg);
        return sum/count;
    }

    说明:

    此代码在固定前两个参数的前提下,后面使用变参

     

  • 相关阅读:
    合并排序法-Java实现
    桶排序(heap sort)-Java实现
    Shell排序法-Java实现
    快速排序法-Java实现
    选择排序法-Java实现
    树状数组例题-数星星,简单题easy,校门外的树2,清点人数
    [USACO]骑马修栅栏 Riding the Fences
    tarjan 割点
    [USACO07OPEN]便宜的回文Cheapest Palindrome
    [AHOI2009]维护序列
  • 原文地址:https://www.cnblogs.com/yiyide266/p/9435634.html
Copyright © 2011-2022 走看看