[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绝对不能为以下类型:

——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 = 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\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 = 0;

int main(void)
{
    printf("Average = %.6lf\n", 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\n", value);
        sum += value;
        ++count;
    }
    va_end(parg);
    return sum/count;
}

说明:

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

原文地址:https://www.cnblogs.com/yiyide266/p/9435634.html

时间: 2024-10-12 04:23:19

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

C 可变长参数运用-----编写Lua的通用调用函数

1.C可变长参数 printf这个使用频繁的C语言函数的参数列表包含一个const char*的描述串,还有一个可变长参数(...) ,如下为printf的函数声明. int printf(const char * __restrict, ...) 在stdarg.h这个头文件中包含着对可变长参数进行操作的一些宏(x86平台为例): #define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( 

C语言可变长参数实现原理

博客:存储系统研究 微博:http://weibo.com/u/2203007022             (1)      C语言可变参数 我们可以从C语言的printf得出可变参数的作用,printf函数的原型如下: int printf ( const char * format, ... ); 通过使用可变个数参数,就是传入的参数个数是可变的,如printf需要根据format实参传入多个实参. (2)      C语言可变参数的使用 下面一个函数myprintf是自己实现的比较简单的

深度探索C语言函数可变长参数

通常我们使用的C函数的参数个数都是固定的,但也有不固定的.比如printf()与scanf().如何自己动手实现一个可变参数函数,这个还是有点技巧的. 我们最常用的就是定义一个宏,使用printf或者printk,如下 #define wwlogk(fmt, args...) printk(fmt, ## args) 现在我们自己动手实现一个可变参数的函数,后面分析原理.首先看一个例子: #include <stdio.h> #include <stdarg.h> int Sum(

C 可变长参数

前面说到可变长参数: 最后重要的是:第一个参数为后面的参数的形式,format.i.e. printf 在这篇中想说的是不安全的问题 -.-!其实就是我瞎搞 先上代码 #include <stdio.h> #include <stdlib.h> #include <stdarg.h> void subfunc(char *format,...){ int i; va_list ap; va_start(ap,format); for(i=0;format[i]!='\0

C语言可变长参数 思考

1.我们为什么需要可变长参数 各种编程语言,如C.C++.java等都实现了可变长参数的函数.普通函数的参数个数是确定的,如果同一个函数可以接受不同数目的参数就需要适用到可变长度的参数.可变长度参数一个最典型的例子就是printf和scanf.以printf为例子,如可以有printf("Hello Word"),printf("Hello word%s","!"),printf("Hello word%s%d","

可变长参数的函数的写法

c语言中的可变长参数的函数小例子: #include <stdio.h> #include <stdarg.h> #include <assert.h> static int pp; void func1() { static int pp1; printf("hello world\n"); } void tiny_printf(char *format, ...) { int i; va_list ap; va_start(ap, format)

关于C中可变长参数

前言 可变长参数指函数的参数个数在调用时才能确定的函数参数.基本上各种语言都支持可变长参数,在特定情形下,可变长参数使用起来非常方便.c语言中函数可变长参数使用"..."来表示,同时可变长参数只能位于固定参数的后面,固定参数的个数至少为1.只要学习过c语言的,应该都知道printf函数,并且见识到了其强大的功能--事实上,迄今为止,我仍认为这是c函数库中最牛逼的函数之一. 一.一个简单的例子 #include <string>  #include <stdio>

va_start、va_end、va_arg 实现可变长参数

/*******************************///va_start.va_end.va_arg 实现可变长参数/*******************************/ #include <stdarg.h>#include <stdio.h> #define END_NUM -1void trease_array(int first_num,...){ int result1 = 0; int result2 = 0; int temp = 0; va

Java中可变长参数的使用及注意事项

在Java5 中提供了变长参数(varargs),也就是在方法定义中可以使用个数不确定的参数,对于同一方法可以使用不同个数的参数调用,例如print("hello");print("hello","lisi");print("hello","张三", "alexia");下面介绍如何定义可变长参数 以及如何使用可变长参数. 1. 可变长参数的定义 使用...表示可变长参数,例如 prin