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

大家熟悉的函数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. 编写OC高质量的代码的有效方法

    1. 写这个只是为了自己记忆,有相关pdf文件,如需要留下邮箱.. 2. 在类的头文件中尽量少引入其他头文件 除非确有必要,否则不要引入头文件.一般来说,应在某个类的头文件中使用向前声明来提及别的类( ...

  2. [转载]解决sudo: sorry, you must have a tty to run sudo

    前几天遇到一个问题,在一个终端中调用另一个shell,始终是无法执行的,后来捕捉到报错信息为sudo: sorry, you must have a tty to run sudo,后来,在网上了解到 ...

  3. ionic build android 中的报错详细原因以及解决方法

    一.执行打包命令 ionic build android 1.报错: 原因: 其实也并非报错,但是会一直在下载gradle,由于网络或者其他原因,导致下载比较慢, 解决方案: 手动下载gradle,并 ...

  4. SharePoint2013上传列表模板(后缀stp)

    在根网站操作

  5. mysql数据库快速入门(1)

    1.数据库操作 1.1.连接mysql服务器 mysql -u root( 用户名 ) -p 1.2.退出mysql命令提示窗 exit 1.3.查看版本 SELECT VERSION(); 1.4. ...

  6. d3 画地图终极自适应大小方案

    d3,v4以前用d3画地图的时候,为了让地图差不多正好画在容器的上下左右正中间,不得不慢慢的这样调: const projection = d3.geoMercator() .center([108. ...

  7. MacBook安装Win10

    // 这是一篇导入进来的旧博客,可能有时效性问题. (一)  确认你的机型 以下机型支持: ü  安装64 位版本Win10 ü  不使用U盘安装Windows l  MacBook(Retina 显 ...

  8. bzoj:1675 [Usaco2005 Feb]Rigging the Bovine Election 竞选划区

    Description It's election time. The farm is partitioned into a 5x5 grid of cow locations, each of wh ...

  9. A. Two Bases

    A. Two Bases time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  10. python笔记三(面向对象)

    Python3 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触 ...