大多数时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数。但在某些情况下希望函数的参数个数可以根据需要确定。典型的例子有

大家熟悉的函数printf()、scanf()

  可变参数的实现:

  C语言头文件stdarg.h提供了一个数据类型va-list和三个宏(va-start、va-arg和va-end),va—start使vp指向第一个可选参数。va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数。va
 
—end把vp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va—start开始,并以va—end结尾。用它们在被调用函数不知道参数个数和类型时对可变参数表进行测试,从而为访问可变参数提供
 
了方便且有效的方法。va-list是一个char类型的指针,当被调用函数使用一个可变参数时,它声明一个类型为va-list的变量,该变量用来指向va-arg和va-end所需信息的位置。
 
下面给出va_list在C中的源码:
    typedef char * va_list; 

  采用ANSI标准形式时,参数个数可变的函数的原型声明是:

     type funcname(type para1, type para2, ...) 
  这种形式至少需要一个普通的形式参数,后面的省略号不表示省略,而是函数原型的一部分,type是函数返回值和形式参数的类型。
 
  调用者在实际调用参数个数可变的函数时,要通过一定的方法指明实际参数的个数,例如把最后一个参数置为空字符串。
  
  下面给出一个具体的例子:
求n个数的和:
int Sum(int n,...)
{
int i = ,sum = ;
va_list vp;
va_start(vp,n); //va—start使vp指向第一个可选参数
for (i=; i<n; i++)
{
sum +=va_arg(vp,int);
}
va_end(vp); //va—end把vp指针清为NULL。
return sum;
}

printf函数实现:(此处只实现了基本类型的打印)

 void my_print(const char *format,...)
{
char c = ;
va_list vp;
va_start(vp,format); //vp指向第一个可选参数
while (*format)
{
c = *format;
switch (c)
{
case '%':
{
char cc = *(++format);
switch (cc)
{
case 'd':
{
char str[];
int n = va_arg(vp,int); //va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数。
char *string = _itoa(n,str,); //把整数转为字符串
print_str(string);
}
break;
case 'f':
{
char str[];
double f = va_arg(vp,double);//va—arg返回参数列表中的当前参数并使vp指向参数列表中的下一个参数
char *string = _gcvt(f,,str);//将浮点型数转换为字符串,取四舍五入
print_str(string);
}
break;
case 'c':
putchar(va_arg(vp,char));
break;
case 's':
{
char *string = va_arg(vp,char*);
print_str(string);
}
break;
default:
break;
}
}
break;
default:
putchar(c);
break;
}
format++;
}
52  va_end(vp);
53 }

理解可变参数很重要的是要理解函数栈帧的创建与销毁,里面涉及到参数是如何压栈,这方面内容在前面的博客:http://www.cnblogs.com/zhonglongbo/p/8392026.html

 

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

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

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

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

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

  3. C语言中的可变参数函数

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

  4. 【C/C++开发】C语言实现函数可变参数

    函数原型: int printf(const char *format[,argument]...)        返 回 值: 成功则返回实际输出的字符数,失败返回-1.  函数说明:        ...

  5. C语言之函数可变参数

    先上一段代码: #include<cstdarg> #include<iostream> #include<string> using namespace std; ...

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

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

  7. python中函数的参数解析

    python中函数的各种参数梳理: 1.形参:函数定义时传入的参数 2.实参:函数调用时传入的参数 (有形参必传实参,形参里自身特点可不传的,可传可不传) 3.缺省参数:不传为默认值,传了会覆盖(下面 ...

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

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

  9. python-函数中的参数类型和可变参数解析

    最近,在学习python,天天抱着廖雪峰的教材苦练,https://www.liaoxuefeng.com/ 但廖老毕竟是如此的才华盈溢,我这等小辈真是读起来教程都有些费力. 关于python-函数中 ...

随机推荐

  1. JavaScript对于switch语句中的case后键入值的带不带引号

    一.用switch选择星期几 这时case为  例:case="星期一" 二.用switch选择单纯的数字 这时case为  例:case='1' 三.用switch选择一个应用了 ...

  2. 关于java中,json字符串转集合和对象,或者集合转json字符串的解决方法

    1 List集合转成json字符串 //Java集合 List<String> list = new ArrayList<String>(); list.add("a ...

  3. deeplearning.ai 改善深层神经网络 week2 优化算法 听课笔记

    这一周的主题是优化算法. 1.  Mini-batch: 上一门课讨论的向量化的目的是去掉for循环加速优化计算,X = [x(1) x(2) x(3) ... x(m)],X的每一个列向量x(i)是 ...

  4. 【干货分享】dos命令大全

    一般来说dos命令都是在dos程序中进行的,如果电脑中安装有dos程序可以从开机选项中选择进入,在windows 系统中我们还可以从开始运行中输入cmd命令进入操作系统中的dos命令,如下图: 严格的 ...

  5. CTF---安全杂项入门第一题 丘比龙的最爱

    丘比龙的最爱分值:10 来源: 2014HCTF 难度:易 参与人数:4498人 Get Flag:1366人 答题人数:1384人 解题通过率:99% 传说,丘比龙是丘比特的弟弟,丘比龙是一只小爱神 ...

  6. [51nod1213]二维曼哈顿距离最小生成树

    二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离).求这N个点所组成的完全图 ...

  7. 什么是 core dump ? 以及如何使用gdb对 core dumped 进行调试

    什么是core dump?(down = 当) core的意思是:内存,dump的意思是:扔出来.堆出来. 开发和使用linux程序时,有时程序莫名其妙的down掉了,却没有任何的提示(有时候会提示c ...

  8. Dora.Interception, 一个为.NET Core度身打造的AOP框架:不一样的Interceptor定义方式

    相较于社区其他主流的AOP框架,Dora.Interception在Interceptor提供了完全不同的编程方式.我们并没有为Interceptor定义一个接口,正是因为不需要实现一个预定义的接口, ...

  9. 我的第一个python web开发框架(20)——产品发布(部署到服务器)

    首先按上一章节所讲述的,将服务器环境安装好以后,接下来就是按步骤将网站部署到服务器上了. 我们的站点是前后端分离的,所以需要部署两个站点.首先来发布前端站点. 部署前端站点 输入命令进入svn管理文件 ...

  10. android studio升级2.3后出现的问题

    报错: Error:Execution failed for task ':app:javaPreCompileDebug'. > Annotation processors must be e ...