C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: 
int printf( const char* format, ...);

它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的(用三个点“…”做参数占位符),实际调用时可以有以下的形式: 
printf("%d", i); 
printf("%s", s); 
printf("the number is %d ,string is:%s", i, s);

一个简单的可变参数的C函数 
先看例子程序。该函数至少有一个整数参数,其后占位符…,表示后面参数的个数不定。在这个例子里,所有的输入参数必须都是整数,函数的功能只是打印所有参数的值。函数代码如下:

//示例代码1:可变参数函数的使用
#include<stdio.h>
#include<stdarg.h> void simple_va_fun(int start, ...)
{
va_list arg_ptr;
int nArgValue = start;
int nArgCout = ; //可变参数的数目 ;
va_start(arg_ptr, start); //以固定参数的地址为起点确定变参的内存起始地址;
do
{
++nArgCout;
printf("the %d th arg: %d\n", nArgCout, nArgValue);//输出各参数的值 ;
nArgValue = va_arg(arg_ptr, int); //得到下一个可变参数的值 ;
}while(nArgValue != -);
return;
} int main()
{
simple_va_fun(, -);
simple_va_fun(, , -);
return ;
}

下面解释一下这些代码。从这个函数的实现可以看到,我们使用可变参数应该有以下步骤: 
⑴由于在程序中将用到以下这些宏: 
void va_start( va_list arg_ptr, prev_param ); 
type va_arg( va_list arg_ptr, type ); 
void va_end( va_list arg_ptr ); 
va在这里是variable-argument(可变参数)的意思。 
这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件。

⑵函数里首先定义一个va_list型的变量,这里是arg_ptr,这个变量是存储参数地址的指针。因为得到参数的地址之后,再结合参数的类型,才能得到参数的值。

⑶然后用va_start宏初始化⑵中定义的变量arg_ptr,这个宏的第二个参数是可变参数列表的前一个参数,即最后一个固定参数。

⑷然后依次用va_arg宏使arg_ptr返回可变参数的地址,得到这个地址之后,结合参数的类型,就可以得到参数的值。

⑸设定结束条件,这里的条件就是判断参数值是否为-1。注意被调的函数在调用时是不知道可变参数的正确数目的,程序员必须自己在代码中指明结束条件。至于为什么它不会知道参数的数目,在看完这几个宏的内部实现机制后,自然就会明白。

C语言中的可变参数函数的更多相关文章

  1. C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .

    我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...

  2. C语言中的可变参数-printf的实现原理

    C语言中的可变参数-printf的实现原理 在C/C++中,对函数参数的扫描是从后向前的.C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出 ...

  3. PHP中的可变参数函数和可选参数函数

    1)可选参数函数.例如: <?phpfunction add($var1,$var2,$var3=0,$var4=0){ return$var1+$var2+$var3+$var4;}echo ...

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

    顾名思义,可变参数函数就是参数数量可变的函数,即函数的参数数量是不确定的,比如方法getnumbertotal()我们即可以传递一个参数,也可以传递5个.6个参数 #include <stdio ...

  5. c语言中的# ## 可变参数宏 ...和_ _VA_ARGS_ _

    1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串.例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字 ...

  6. 各种语言中的可变参数(java、python、c++、javascript)

    索引: java python c++ js 1.Java public class Animal { // 接受可变参数的方法 void eat(String... Objects) { for ( ...

  7. C语言如何在可变参数函数中使用printf?

    我要将printf外面再包上一层:void fun(const char* fmt,...) {........printf(fmt,...);........}这种函数怎么写? 对比下printf与 ...

  8. Swift开发第十篇——可变参数函数&初始化方法顺序

    本篇分为两部分: 一.Swift中的可变参数函数 二.初始化方法的顺序 一.Swift中的可变参数函数 可变参数函数指的是可以接受任意多个参数的函数,在 OC 中,拼接字符串的函数就属于可变参数函数 ...

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

    C函数调用的栈结构 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈.例如,对于函数: void fu ...

随机推荐

  1. (2.15)Mysql之SQL基础——开发设计最佳规范

    (2.15)Mysql之SQL基础——开发设计最佳规范 关键字:mysql三大范式,mysql sql开发规范 分析: show profile.mysqllsla.mysqldrmpslow.exp ...

  2. 如何确定Hadoop中map和reduce的个数--map和reduce数量之间的关系是什么?

    一般情况下,在输入源是文件的时候,一个task的map数量由splitSize来决定的,那么splitSize是由以下几个来决定的 goalSize = totalSize / mapred.map. ...

  3. vuejs和webpack项目(VueComponent)初尝试——瀑布流组件

    碎碎念:     好久不见,最近自己有些懈怠没更过多少博,主要原因之一是对自己学习方式的一些思考,翻看之前的博客多是记录学习笔记这反映出了自己对于前端还停留在学习-复习知识点的阶段压根没多少实践经验啊 ...

  4. PAT 1090 Highest Price in Supply Chain[较简单]

    1090 Highest Price in Supply Chain(25 分) A supply chain is a network of retailers(零售商), distributors ...

  5. spring基础-01

    IOC : inversion of 缩写, DI:dependency injection 即在调用者中注入被调用者的实例. AOP 面向切面编程,是代理模式的体现.spring默认使用JDK的动态 ...

  6. laravel 项目部署注意事项

    1.'Failed to open stream: Permission denied' error - Laravel Laravel >= 5.4 php artisan cache:cle ...

  7. Vue-cli proxyTable 解决开发环境的跨域问题

    Vue-cli proxyTable 解决开发环境的跨域问题 proxyTable: { '/list': { target: 'http://api.xxxxxxxx.com', pathRewri ...

  8. FCKeditor配置与使用

    fckeditor - (1)资料介绍与安装 fckeditor介绍  FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器.  1.fckeditor官网:http://ww ...

  9. Underscore-逐行分析

    标签: // Underscore.js 1.8.3// http://underscorejs.org// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud ...

  10. Python3.x:os.path模块

    Python3.x:os.path模块 #返回绝对路径 os.path.abspath(path) #返回文件名 os.path.basename(path) #返回list(多个路径)中,所有pat ...