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. mysql实现开窗函数、Mysql实现分析函数

    关键字:mysql实现开窗函数.Mysql实现分析函数.利用变量实现窗口函数 注意,变量是从左到右顺序执行的 --测试数据 CREATE TABLE `tem` ( `id` ) NOT NULL A ...

  2. android 异步线程刷新UI 以及 JSON解析 以及 url get请求

    import android.os.Handler; import android.os.Message; 1. Handler mHandler = new Handler() { @Overrid ...

  3. hadoop中map和reduce的数量设置

    hadoop中map和reduce的数量设置,有以下几种方式来设置 一.mapred-default.xml 这个文件包含主要的你的站点定制的Hadoop.尽管文件名以mapred开头,通过它可以控制 ...

  4. hive两大表关联优化试验

    呼叫结果(call_result)与销售历史(sale_history)的join优化: CALL_RESULT: 32亿条/444G SALE_HISTORY:17亿条/439G 原逻辑 Map: ...

  5. Django:学习笔记(8)——文件上传

    Django:学习笔记(8)——文件上传 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不 ...

  6. Java 动态代理是基于什么原理

    动态代理 ①动态代理概念理解 动态代理是一种方便运行时动态构建代理.动态处理代理方法调用的机制,很多场景都利用类似机制做到的,比如用来包装RPC调用.面向切面的变成(AOP) 实现动态代理的方式很多, ...

  7. JSDoc 注释规范

    命令名描述 @param @argument 指定参数名和说明来描述一个函数参数@returns 描述函数的返回值@author 指示代码的作者@deprecated 指示一个函数已经废弃,而且在将来 ...

  8. DB开发之大数据量高并发的数据库优化

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  9. 关于GET POST

    先说相同点,只有了解了相同点之后才能理解为什么会发生混淆.两者都能向服务器发送数据,提交的“内容”[注1]的格式相同,都是var_1=value_1&var_2=value_2&... ...

  10. Python3.x获取网页源码

    Python3.x获取网页源码 1,获取网页的头部信息以确定网页的编码方式: import urllib.request res = urllib.request.urlopen('http://ww ...