c语言之可变参数函数

stdarg.h

stdarg.h是C标准函数库的头文件,主要目的是为让函数能够接收不定参数。当需要定义可变参数函数时,需要包含该头文件。

先从一个例子说起,这个例子想法来自<<head first c>>

#include <stdio.h>
#include <stdarg.h>

enum drink{apple = 3,banana = 4,orange = 5,other = 6};

int count(int n,...)
{
    int total = 0;

    va_list ap;
    va_start(ap,n);

    for (int i = 0; i < n; ++i) {
        total += (int) va_arg(ap, enum drink);
    }
    va_end(ap);
    return total;
}

int main()
{
    printf("cost %d\n",count(3,apple,orange,other));
    printf("cost %d\n",count(5,apple,apple,banana,other,orange));
}

该例子定义了一个饮料的类型,并设定好了饮料的价钱。

之后又定义了一个函数count来统计价格,第一个参数表示购买的个数,之后为购买的品种(可变),最后得到花费的总价钱。

//不定参数函数至少有一个命名的参数

输出:

cost 14

cost 21

Program ended with exit code: 0

现在说一下原理:

既然函数至少有一个命名的参数,那么就有了一个基准,就可以定义指针根据该基准变量的地址定位到后续参数的起始地址。

如果再知道后续参数的类型,那么根据参数类型的长度,可以通过指针取得参数的值。

再介绍一下那4个宏的用途:

va_list  : 定义上述的那个指针

va_start  :定位后续变量的地址。由于至少有一个可变参数(可以有多个),根据定位最后一个已知参数来知道后续参数的起始地址。

va_arg :  根据后续参数的类型,通过指针将数据取出。

va_end :    进行一些结束工作

最后回过来解释一下最前面的例子:

先定义了一个指针 va_list  ap;

通过 va_start函数 将指针ap 与已知参数n联系起来,定位到后续参数的起始地址。

定位好之后后通过va_arg函数。利用指针ap和参数类型来获得数据,由于该例子第一个参数是个数,知道for循环要进行求和的次数。

最后结束va_end。

附:

可变参数学习笔记

时间: 2024-10-12 16:40:43

c语言之可变参数函数的相关文章

C语言中可变参数函数实现原理

C函数调用的栈结构 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈.例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x2000-->a 0x2004-->b 0x2008-->c 对于在32位系统的多数编译器,每个栈单元的大小都是sizeof(int), 而函数的每个参数都至少要占一个栈单

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

一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本文地址:http://www.cnblogs.com/archimedes/p/variable-parameter.html,转载请注明源地址. 例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x200

c语言可变参数函数

c语言支持可变参数函数.这里的可变指,函数的参数个数可变. 其原理是,一般情况下,函数参数传递时,其压栈顺序是从右向左,栈在虚拟内存中的增长方向是从上往下.所以,对于一个函数调用 func(int a, int b, int c); 如果知道了参数a的地址,那么,可以推导出b,c的地址 #include <stdio.h> void test(int a, int b, int c) { printf("%p, %p, %p\n", &a, &b, &

【C语言天天练(四)】可变参数函数

可变参数函数指可以接受可变数量参数的函数.比如printf函数就是一个可变参数函数. 要完成可变参数函数的编写,需要用到定义于stdarg.h头文件中的一个类型va_list和三个宏va_start.va_arg.va_end. 注意: 1.可变参数必须从头到尾按照顺序逐个访问.如果在访问几个可变参数后想半途中止,这是可以的.但是,如果想一开始就访问列表中的参数,那是不行的. 2.由于参数列表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升. 3.参数列表

C语言中可变参数的函数(三个点,“...”)

C语言中可变参数的函数(三个点,"...") 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解. 介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理: 1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 void foo(...); void foo(parm_list,...); 这种方式和我们以前认识的不大

C语言中的可变参数函数 三个点“…”printf( const char* format, ...)

第一篇 C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的(用三个点“…”做参数占位符),实际调用时可以有以下的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s",

C语言学习020:可变参数函数

顾名思义,可变参数函数就是参数数量可变的函数,即函数的参数数量是不确定的,比如方法getnumbertotal()我们即可以传递一个参数,也可以传递5个.6个参数 1 #include <stdio.h> 2 #include <stdarg.h>//实现可变参数需要的头文件 3 4 int getnumbertotal(int args,...){//可变参数要放在普通参数(args)的后面:...表示有很多个参数 5 va_list l;//用来保存传给函数的其他参数 6 va

C语言可变参数函数详解示例

先看代码 printf("hello,world!");其参数个数为1个. printf("a=%d,b=%s,c=%c",a,b,c);其参数个数为4个. 如何编写可变参数函数呢?我们首先来看看printf函数原型是如何定义的.在linux下,输入man 3 printf,可以看到prinf函数原型如下: SYNOPSIS #include <stdio.h> int printf(const char *format, ...); 后面的三个点...

【转】C/C++中可变参数函数的实现

转自:http://www.cnblogs.com/cylee025/archive/2011/05/23/2054792.html 在C语言的stdarg.h头文件中提供了三个函数va_start, va_end,va_arg和一个类型va_list.利用它们,我们可以很容易实现一个可变参数的函数.首先简单介绍一下这三个函数. 假设现在有一个名为f的函数,其函数定义为: void f(int a, int b, ...) 那么,在函数的内部,为了获得这些可变参数,就需要利用到va_start.