一、概述

运用标准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绝对不能为以下类型:
——char、signed 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 = ;
char str_2[] = "March & April";
int i_2 = ;
myPrintf(str_1, d_1, i_1, str_2, i_2);
} void myPrintf(const char *format, ...)
{
printf("%s\n", format);
va_list parg;
va_start(parg, format);
printf("%.6lf\n", va_arg(parg, double));
printf("%d\n", va_arg(parg, int));
printf("%s\n", va_arg(parg, char*));
printf("%d\n", 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 = ; int main(void)
{
printf("Average = %.6lf\n", average(0.2, 3.5, 108.625, (double), 0.3, 0.0));
} double average(double v1, double v2, ...)
{
va_list parg;
double sum = v1 + v2;
double value = 0.0;
int count = ; va_start(parg, v2);
while((value = va_arg(parg, double)) != 0.0)
{
printf("Item = %.6lf\n", value);
sum += value;
++count;
}
va_end(parg);
return sum/count;
}

说明:

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

[C]va_list可变长参数的使用的更多相关文章

  1. 可变长参数列表误区与陷阱——va_arg不可接受的类型

    可变长参数列表误区与陷阱--va_arg不可接受的类型 实现一个有可变长参数列表函数的时候,会使用到stdarg.h(这里不讨论varargs.h)中提供的宏. 例如,我们要实现一个简易的my_pri ...

  2. [转]深度探索C语言函数可变长参数

    转自:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html 一.基础部分 1.1 什么是可变长参数 可变长参数:顾名 ...

  3. 关于C中可变长参数

    前言 可变长参数指函数的参数个数在调用时才能确定的函数参数.基本上各种语言都支持可变长参数,在特定情形下,可变长参数使用起来非常方便.c语言中函数可变长参数使用“...”来表示,同时可变长参数只能位于 ...

  4. C语言开发具有可变长参数的函数的方法

    学习交流可加 微信读者交流①群 (添加微信:coderAllen) 程序员技术QQ交流①群:736386324 --- 前提:ANSI C 为了提高可移植性, 通过头文件stdarg.h提供了一组方便 ...

  5. C++ 系列:函数可变长参数

    一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ...

  6. C语言之可变长参数格式化

    概述 本文演示环境: win10 + Vs2015 可变长参数格式化 两个概念: 1. 参数长度不定, 2. 参数格式化. 使用函数 vsnprintf 结合 va_list. 源码 写好了函数, 照 ...

  7. 在Python中使用可变长参数列表

    函数定义 在函数定义中使用*args和**kwargs传递可变长参数. *args用作传递非命名键值可变长参数列表(位置参数); **kwargs用作传递键值可变长参数列表 函数调用 在调用函数时,使 ...

  8. python中非关键字可变长参数和关键字变量参数的区别

    #非关键字可变长参数 def add(*arg):    return type(arg) print add() #打印结果 <type 'tuple'> #关键字变量参数 def ab ...

  9. Java中的可变长参数

    可变长参数的定义 与一般方法没多大差别,只不过形参多了...(三个点) 方法名(数据类型 ... 变量名){} 小案例: public class ParamDemo { public static ...

随机推荐

  1. python位运算

    什么是位运算 位运算就是把数字当成二进制来进行计算,位运算有六种:&(与), |(或), ^(异或), ~(非), <<(左移), >>(右移) &(与) &a ...

  2. vue 组件动态 循环

    组件可以是动态的,记录如下 <div v-for="item in arrComponent"> <component v-bind:is="item. ...

  3. javascript获取值

    <div id='name'>张三</div> $('#name').val() $(name).val() 以上两个都可以得到值,第一种用的比较多.

  4. Java SE之网络编程:知识框架

  5. Element-ui 中dialog的使用方法

    <template> <div> <el-button type="text" @click="dialogFormVisible = tr ...

  6. python栈

    class StackEmptyError(Exception): pass class StackFullError(Exception): pass class Stack: def __init ...

  7. python 的基础 学习 11天 作业题

    1.整理函数相关知识点,写博客 2.写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者. def func1(argv): li = [] for i in r ...

  8. 执行maven install跳过执行maven test方法(网上搜的记录一下,方面以后使用)

    直接在pom文件加上这段配置就可以了 <plugin>           <groupId>org.apache.maven.plugins</groupId>  ...

  9. 2017-2018-2 20165237 实验三《 敏捷开发与XP实践》实验报告

    2017-2018-2 20165237 实验三< 敏捷开发与XP实践>实验报告 实验报告表头: 知识点: 1.XP团队使用现场客户.特殊计划方法和持续测试来提供快速的反馈和全面的交流: ...

  10. Vue & webpack

    在webpack构建的项目中使用vue进行开发 在入口文件中 import Vue from 'vue' 导入的构造函数,功能不完整,只提供了runtime-only的方式,并没有提供网页中那样的使用 ...