一、什么是可变参数

在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为:

int printf(const char* format,…)
int scanf(const char *format,…)

它除了有一个参数format固定以外,后面跟着的参数的个数和类型是可变的(用三个点“…”做参数占位符)

二、简单的可变参数例子

#include <stdio.h>
#include <stdarg.h> void print_args(int count, ...); int main(int argc, char* argv[]) {
print_args(5,1,2,3,4,5);
return 0;
} void print_args(int count, ...) {
int i, value;
va_list arg_ptr;
va_start(arg_ptr, count);
for(i=0; i<count; i++) {
value = va_arg(arg_ptr,int);
printf("position %d = %d\n", i+1, value);
}
va_end(arg_ptr);
}

三、对va_arg,va_list,va_start,va_end剖析

可变参数用到以下宏函数:

原型: void va_start(va_list arg_ptr, prev_param); 功能:以固定参数的地址为起点确定变参的内存起始地址,获取第一个参数的首地址

返回值:无

原型:va_list 类型的变量,va_list arg_ptr ,这个变量是指向参数地址的指针,因为得到参数的地址之后,再结合参数的类型,才能得到参数的值。

原型:type va_arg(va_list arg_ptr, type); 功能:获取下一个参数的地址 返回值:根据传入参数类型决定返回值类型

原型:void va_end(va_list arg_ptr); 功能:将 arg_ptr 指针置0 返回值:无

对应于上面的实例,参见下面的示意图,即可明白,

|   5	|		|   5	|		/\	|   5	| <--arg_ptr
| 4 | | 4 | || | 4 |
| 3 | | 3 | || | 3 |
| 2 | | 2 | || | 2 |
| 1 | | 1 | <-- arg_ptr || | 1 |
| 5 | <-- count | 5 | <-- count || | 5 | <-- count

这三个宏的实现细节,可参见下面的 blog:

[1] C中可变参数函数实现

[2] 内存对齐 _INTSIZEOF(n)

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

  1. C语言 可变参数

    一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ...

  2. 转:C语言 可变参数

    C语言 可变参数 堆栈一般是怎么压栈处理的 /* * stack space: * *        参数3   |    up *        参数2   | *        参数1   v   ...

  3. 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)

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

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

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

  5. ios 可变参数(va_list,va_start,va_end)

    例如:UIAlertView的init方法中的otherButtonTitles:(NSString *)otherButtonTitles, ...等多个可变参数. ios实现传递不定长的多个参数的 ...

  6. C语言可变参数函数的编写

    1. 引言 C语言我们接触的第一个库函数是 printf(“hello,world!”);其参数个数为1个. 然后,我们会接触到诸如: printf(“a=%d,b=%s,c=%c”,a,b,c);此 ...

  7. C语言可变参数

    前段时候在实现利用redis进行的一个数据库比对的功能,稍微去分析了一下redis里面的源代码,然后发现其中的发送命令接口声明如下: void *redisCommand(redisConnect * ...

  8. c语言可变参数函数

    c语言支持可变参数函数.这里的可变指,函数的参数个数可变. 其原理是,一般情况下,函数参数传递时,其压栈顺序是从右向左,栈在虚拟内存中的增长方向是从上往下.所以,对于一个函数调用 func(int a ...

  9. Go语言 可变参数

    最近与同事讨论时,提到Go语言的可变参数,之前没有总结过相关知识点,今天我们介绍一下Go语言的可变参数. 可变参数(Variable Parameters):参数数量可变的函数称之为可变参数函数,主要 ...

随机推荐

  1. Mahout fp-growth

    FP-growth Apriori算法的一个主要瓶颈在于,为了获得较长的频繁模式,需要生成大量的候选短频繁模式.FP-Growth算法是针对这个瓶颈提出来的全新的一种算法模式.目前,在数据挖掘领域,A ...

  2. SpriteBuilder中不能编辑自定义类或不能给节点添加属性的解决

    不能编辑自定义类 你选中一个Sub File(CCBFile)节点,在这个例子中,该节点的Custom class区域灰化禁用且不能修改.这是因为你需要在该Sub File引用的CCB文件中修改Cus ...

  3. 漫谈程序员(十)大白菜装机版安装win7系统使用教程

    大白菜装机版安装win7系统使用教程 安装win7系统准备工作: ①使用大白菜装机版,制作一个大白菜u盘启动盘 ②将下载好的ghost win7系统镜像包放入制作好的大白菜u盘启动盘中. ③更改电脑硬 ...

  4. STL常用遍历算法for_each和transform的比较

    for_each()和transform()算法比较 1)STL 算法 – 修改性算法  for_each()  copy()  copy_backward()  transform()  merge ...

  5. ActiveX数据对象之事务控制在VB和DELPHI中的应用

            本文发表在中国人民解放军"信息工程大学"学报 2001年第3期.        ActiveX数据对象之事务控制在VB和DELPHI中的应用             ...

  6. C++之标准输入输出

    由于在公司,无法上传图片,往后补上. 关于C++的标准输入输出,其实就相当于C语言的scanf和printf,只不过C++用cin和cout这样称为流的机制. #include <iostrea ...

  7. EBS form 之间跳转实现(form 关闭)

    实现 form CUXOMWB 使用 app_navigate.execute 打开 form CUXOEXPRAVA :然后 FROM CUXOEXPRAVA 上点击按钮 跳回from CUXOMW ...

  8. 【52】java多线程剖析

    线程的状态: 线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的s ...

  9. 双系统或三系统:Grub Rescue修复方法

    我是在装三系统的时候(1.WIN 7 ,2.Ubuntu 12.04 ,3.CentOS 6.4 ),中间步骤出错,造成引导区覆盖,grub乱掉了. 症状: 开机显示:GRUB loading err ...

  10. DB Query Analyzer 5.02 is distributed, 53 articles concerned have been published

    DB Query Analyzer is presented by Master Gen feng, Ma from Chinese Mainland. It has English version ...