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

大家熟悉的函数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. java equals == contentEquals

    equals与== 经常用于比较,用法如下:字符串比较相同用equals,普通数值(基本数据类型)比较用==, contentEquals下面讲 理论准备: java的基本类型如int.float,d ...

  2. 深入理解ES6之—符号与符号属性

    在js已有的基本类型(字符串,数值,布尔型,null和undefined)之外,es6引入了一种新的基本类型:==符号(Symbol)==.符号起初被设计用于创建对象私有成员. 符号没有字面量形式,你 ...

  3. [转] Web 开发模式演变历史和趋势

    文章转自梦想天空--前端文摘:Web 开发模式演变历史和趋势 一.简单明快的早期时代 可称之为 Web 1.0 时代,非常适合创业型小项目,不分前后端,经常 3-5 人搞定所有开发.页面由 JSP.P ...

  4. python实现类jq的json路径过滤

    开发过程中访问接口时经常用到jq来过滤json,用着觉得不是很爽,于是自己搞一个舒服的 ^_^ 先说需求: 输入:参数1:被过滤对象(json.dict.list), 参数2:过滤路径 输出:过滤结果 ...

  5. java.lang.Class类中的某些方法

    反射的代码会经常遇到,Class类中方法真的多,且用的少,大多用在底层源码这块,既然看到了,就记录一下吧,说不定以后厉害了,自己封装框架,haha getComponentType()方法: Syst ...

  6. python通过getopt模块获取执行命令参数

    python脚本和shell脚本一样可以获取命令行的参数,根据不同的参数,执行不同的逻辑处理. 通常我们可以通过getopt模块获得不同的执行命令和参数. 下面我通过新建一个test.py的脚本解释下 ...

  7. VS工程中添加c/c++工程中外部头文件及库的基本步骤

    转载自 在VS工程中,添加c/c++工程中外部头文件及库的基本步骤: 1.添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录. 2.添加 ...

  8. HDU 1003 Max Sum【动态规划求最大子序列和详解 】

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  9. printf不能直接输出string类型

    因为string不是c语言的内置数据,所以直接printf输出string类型的是办不到的.要这样输出: printf("%s\n",a.c_str()); 举例: #includ ...

  10. BZOJ3237: [Ahoi2013]连通图

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3237 cdq分治+缩点. 可以每次处理的时候把除l~r之外的边的端点都连起来.然后去跑cdq分 ...