C语言利用va_list、va_start、va_end、va_arg宏定义可变參数的函数
在定义可变參数的函数之前,先来理解一下函数參数的传递原理:
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宏定义可变參数的函数的更多相关文章
- OC可变參数的函数实现va_start、va_end、va_list的使用
一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...
- C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数
在定义可变参数的函数之前,先来理解一下函数参数的传递原理: 1.函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈. 2.参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在 ...
- va_list va_start va_end va_arg 解决变参问题
解决参数个数不确定的问题. 头文件 #include<stdarg.h> VA_LIST 是在C语言中解决变参问题的一组宏,用于获取不确定个数的参数. #ifdef _M_ALPHA ty ...
- c 语言函数可变參数的处理
/************************************************************************* > File Name: va_list.c ...
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...
- 利用 Excel 写 C51 的宏定义
利用 Excel 写 C51 的宏定义 填好占空比,自动生成宏. #define LIGHT_LEVEL_00 0xFF #define LIGHT_LEVEL_10 0xE5 #define LIG ...
- 关于Netfilter NF_HOOK宏的outdev參数bug
1.首先指出.NF_HOOK系列宏的outdev參数的传递方式(直接传递一个net_device结构体指针)是不对的 正确的方式要么是不传递.要么是传递指针的地址,即地址的地址. 2.接下来指出,仅仅 ...
- 对va_list; va_start ; va_end ;vsprintf理解(转)
以下为转载内容: int printf(const char* fmt, ...) { va_list args; int i; //1.将变参转化为字符串 va_start(args,fmt); v ...
- C语言,调试必备的DEBUG宏定义
1. #include <stdio.h> #include <stdarg.h> //仅仅是打印函数名字替换 DEBUG <--> printf #define ...
随机推荐
- 大数据的胖哥的方式(9)- 金融业数据仓库的逻辑模型FS-LDM
介绍: 大数据是不是海市蜃楼,来自小橡子只是意淫奥克斯,大数据的发展,而且要从头开始,基于大数据建设国家.项目-level数据中心行业将越来越多,大数据仅供技术,而非溶液,临数据组织模式,数据逻辑模式 ...
- POJ 3076 Sudoku DLX精确覆盖
DLX精确覆盖模具称号..... Sudoku Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 4416 Accepte ...
- Oracle SQL 调优健康检查脚本
Oracle SQL 调优健康检查脚本 我们关注数据库系统的性能,进行数据库调优的主要工作就是进行SQL的优化.良好的数据架构设计.配合应用系统中间件和写一手漂亮的SQL,是未来系统上线后不出现致命性 ...
- ASP.NET MVC (Razor)开发
ASP.NET MVC (Razor)开发 过去我们使用过一些周报工具来完成项目组或部门的周报填写与考核工作,但多少有些不理想,要么功能太过简单,要么功能特别繁杂,不接地气,使用不便. 后来我们就考虑 ...
- iOS UISearchDisplayController学习笔记
UISearchDisplayController和UISearchBar一起使用用来管理UISearchBar和搜索结果的展示.UISearchDisplayController提供了显示搜索结果的 ...
- HDOJ 3480 Division
斜率优化DP. ... 对数组排序后.dp[i][j]表示对前j个物品分i段的最少代价,dp[i][j]= min{ dp[i-1][k]+(a[k+1]-a[j])^2 }复杂度m*n^2 ...
- oracle数据库全然恢复和不全然恢复以及运行用户管理辈分恢复
比較全然恢复和不全然恢复: 一.全然恢复:将数据库恢复到当前最新状态,包含直至请求恢复时进行的全部已提交的数据更改 二.不全然恢复:将数据库恢复到请求恢复操作之前指定的过去时间点 一.全然恢复过程 以 ...
- hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树
题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...
- 设计模式--模板方法 And State模式
1.模板方法 钩子: 在抽象基类已经有默认的定义,子类选择是否覆盖它 在模板方法模式中, 抽象基类中使用 钩子函数(子类视情况是否覆盖) 来达到控制模板方法中 流程控制的 目的 设计原则: ...
- 使用C++实现功能下载文件
今天问一个同学C++实现的下载链接下载并保存给定的文件,互联网搜索.看到这样的事情在网上.因此,改变下直接带来,因为他的代码是在VC++,我导入到VS2010中出现点小问题.所以改了下贴了个VS中亲測 ...