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 ...
随机推荐
- Java操作memcached(一)
Memcached事实上,两次Hash算法 第一次hash算法被用于定位Memcached示例 第二次hash算法是底部HashMap中间hash算法 Hash算法 1.依据余数 ...
- 如何获得SQL Server索引使用情况
原文:如何获得SQL Server索引使用情况 原文出自: http://www.mssqltips.com/sqlservertip/1239/how-to-get-index-usage-info ...
- Linux磁盘分区,目录树,文件系统的关系(转)
研究了很久,自始至终不能够从三者的区别和联系中找到一个大脑与这些概念之间合适的相处方式.对于基本概念和理论理解不到位,在工作之中会走很多弯路和犯很多错误.今天花一天的时间,终于对三者的区别和联系有了更 ...
- OpenNMS在安装”我找不到jrrd.dll“错误的解决方法
在Windows 2003 Server(虚拟机)安装OpenNMS.找不到jrrd.dll错误.尝试从学习OpenNMS官网下载jrrd-1.0.7.tar.gz,我们没有发现标dll文件,编译需要 ...
- T-SQL性能调整——信息收集
原文:T-SQL性能调整--信息收集 IO信息(自服务器启动开始) --Database IO analysis WITH IOFORDATABASE AS ( SELECT DB_NAME(VFS. ...
- hadoop编程小技巧(7)---自己定义输出文件格式以及输出到不同文件夹
代码測试环境:Hadoop2.4 应用场景:当须要定制输出数据格式时能够採用此技巧,包含定制输出数据的展现形式.输出路径.输出文件名称称等. Hadoop内置的输出文件格式有: 1)FileOutpu ...
- android 推断应用程序是系统程序还是用户程序
直接上代码: AppInfo.java <span style="font-size:18px;">package com.example.packages; publ ...
- Advanced Installer 制作.NetWeb部署安装包
原文:Advanced Installer 制作.NetWeb部署安装包 因为是.Net的Web应用程序,所以想用Advanced Installer 调用Dll实现安装部署. 因为我需要自己定制参数 ...
- Go如何使用实现继承的组合
Go它提供了一个非常值得称道的并发支持,但Go它不支持完全面向对象的.这并不意味着Go不支持面向对象,,和Go的OO系统做的很轻巧,学习降至最低成本.向对象让Go失去了一些OO的方便特性,可是更高的效 ...
- Session or Cookie?是否有必要使用Tomcat等一下Web集装箱Session
Cookie是HTTP协议标准下的存储用户信息的工具.浏览器把用户信息存放到本地的文本文件里. Session是基于Cookie实现的. 2011年4月,武汉群硕面试的时候(实习生).面试官也问过这个 ...