在定义可变參数的函数之前,先来理解一下函数參数的传递原理:

1、函数參数是以栈这样的数据结构来存取的,在函数參数列表中,从右至左依次入栈。

2、參数的内存存放格式:參数的内存地址存放在内存的堆栈段中,在运行函数的时候,从最后一个(最右边)參数開始入栈。因此栈底高地址,栈顶低地址,举个样例说明一下:

void test(int a, float b, char c);

那么,在调用test函数的时候,实參char c先进栈,然后是float b,最后才是int a,因此在内存中变量的存放次序是c->b->a,由于从理念上来说,我们仅仅要探測到随意一个变量的地址,而且知道其他变量的类型,通过指针移位运算,就能够顺藤摸瓜找到其他的输入变量。

实现一个可变參数的函数,须要用到下面几个宏:

typedef char* va_list;	// 用于声明一个指向參数列表的字符型指针变量
void va_start(va_list ap, prev_param); // 第一个參数为指向可变參数字符指针变量,第二个參数是可变參数的第一个參数,通经常使用于指定可变參数列表中參数的个数
void va_arg(va_list ap, type); // 第一个參数为指向可变參数字符指针变量,第二个參数是可变參数的数据类型
void va_end(va_list ap);// 将存放可变參数字符串的变量清空(赋值为NULL)

3、演示样例:求N个数的和

int sum(int count, ...)
{
int sum = 0;
int i;
va_list ap;
va_start(ap, count);
for (i = 0; i < count; ++i)
{
sum += va_arg(ap, int);
}
va_end(ap);
return sum;
}
int main(int argc, const char * argv[])
{
int ret = sum(5, 1, 2, 3, 4, 5);
printf("sum: %d\n",ret);
}

4、演示样例:标准库可变參数的相关函数使用

void test(int count,...)
{
va_list ap;
va_start(ap, count);
vprintf("%d,%d,%d\n", ap); // 格式化输出可变參数的值 char buff[1024];
vsprintf(buff, "a=%d,b=%d,c=%d\n", ap); // 将可变參数列表的值格式化输出到缓冲区中
printf("%s\n",buff); vfprintf(stdout, "a=%d,b=%d,c=%d\n", ap); // 将可变參数列表的值打印到标准输出中 // 可变參数传入的是int类型的地址
vsscanf("10,30,40", "%d,%d,%d", ap); // 依次将格式化字符串的值,输入到可变參数变量中 vsnprintf(buff, 30, "a=%d,b=%d,c=%d", ap); // 将可变參数列表的值,格式化输出指定长度(30个字符)的字符串到缓冲区中
printf("vsnprintf=%s\n",buff); va_end(ap);
}

C语言利用va_list、va_start、va_end、va_arg宏定义可变參数的函数的更多相关文章

  1. OC可变參数的函数实现va_start、va_end、va_list的使用

    一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...

  2. C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数

    在定义可变参数的函数之前,先来理解一下函数参数的传递原理: 1.函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈. 2.参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在 ...

  3. va_list va_start va_end va_arg 解决变参问题

    解决参数个数不确定的问题. 头文件 #include<stdarg.h> VA_LIST 是在C语言中解决变参问题的一组宏,用于获取不确定个数的参数. #ifdef _M_ALPHA ty ...

  4. c 语言函数可变參数的处理

    /************************************************************************* > File Name: va_list.c ...

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

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

  6. 利用 Excel 写 C51 的宏定义

    利用 Excel 写 C51 的宏定义 填好占空比,自动生成宏. #define LIGHT_LEVEL_00 0xFF #define LIGHT_LEVEL_10 0xE5 #define LIG ...

  7. 关于Netfilter NF_HOOK宏的outdev參数bug

    1.首先指出.NF_HOOK系列宏的outdev參数的传递方式(直接传递一个net_device结构体指针)是不对的 正确的方式要么是不传递.要么是传递指针的地址,即地址的地址. 2.接下来指出,仅仅 ...

  8. 对va_list; va_start ; va_end ;vsprintf理解(转)

    以下为转载内容: int printf(const char* fmt, ...) { va_list args; int i; //1.将变参转化为字符串 va_start(args,fmt); v ...

  9. C语言,调试必备的DEBUG宏定义

    1. #include <stdio.h> #include <stdarg.h> //仅仅是打印函数名字替换 DEBUG <--> printf #define ...

随机推荐

  1. ZOJ 2412 Farm Irrigation(DFS 条件通讯块)

    意甲冠军  两个农田管内可直接连接到壳体  他们将能够共享一个水源   有11种农田  管道的位置高于一定  一个农田矩阵  问至少须要多少水源 DFS的连通块问题  两个相邻农田的管道能够直接连接的 ...

  2. 系列五AnkhSvn

    原文:系列五AnkhSvn AnkhSvn介绍 AnkhSVN是一款在VS中管理Subversion的插件,您可以在VS中轻松的提交.更新.添加文件,而不用在命令行或资源管理器中提交.而且该插件属于开 ...

  3. 存储管理(两):openfiler它accounts

    存储管理(一个):openfiler演示和存储理解 openfiler的用户集中控制主要分为ldap和ad实现,当中openfiler本身可以作为ldapserver.使openfiler上的全部功能 ...

  4. 孙陪你,了解它的权力--Kinect结合的发展Unity3D游戏应用开发

    unity3d正在使用kinect三维模型数据控制(它切成脚本) 博主在做项目时须要利用kinect数据控制三维模型中人物的动作.但不是实时控制,而是利用之前获得的骨骼数据,直接控制.无需再利用脚本打 ...

  5. 使用SQLServer 2008的CDC功能实现数据变更捕获

    原文:使用SQLServer 2008的CDC功能实现数据变更捕获 最近由于工作需要,研究了一下2008 CDC功能,觉得还不错,下面整理了一下研究过程,虽然比较粗略,但是基本上能用了,如果有补充请大 ...

  6. Android docs4.3API

    查找在线课程,加速进入Android docs API,最主要的原因是网上加载js文件速度慢,另一种是装google字体缓慢! import java.io.BufferedReader; impor ...

  7. Linux下find命令具体解释

    1. find命令 linux的find命令用来查找文件,功能非常强大, 能够通过时间, 用户组, 文件名称, 文件类型, 权限,大小等来查找对应文件. 2. find的使用方法 通过find --h ...

  8. swift类名称显示变量

    <span style="background-color: rgb(255, 255, 255); color: rgb(51, 51, 51); font-family: Aria ...

  9. mvc验证jquery.unobtrusive-ajax

    Unobtrusive Ajax Ajax (Asynchronous JavaScript and XML 的缩写),如我们所见,这个概念的重点已经不再是XML部分,而是 Asynchronous ...

  10. android4.4组件分析--service组件-bindService源代码分析

    6.1.1.    bindService 由于有前面分析startService的代码实现过程,则对于bindService的代码分析就不用那么具体介绍,在介绍流程的同一时候更关注一些细节上的部分. ...