C/C++中带可变参数的函数
1.带可变参数的函数由来
当函数中的参数个数不确定时,这时候就需要带可变参数的函数!
如我们经常使用的C库函数printf()实际就是一个可变参数的函数,
其原型为:
int printf( const char* format, ...);
它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的。例如我们可以有以下不同的调用方法:
printf( "%d ",i);
printf( "%s ",s);
printf( "the number is %d ,string is:%s ", i, s);
2.带可变参数函数的实现,
原理:
- 使用了指针参数来解决参数的可变问题,指针参数随着其移动指向不同的参数;
- C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数。
C语言标准库中头文件stdarg.h索引的接口包含了一组能够遍历变长参数列表的宏。
头文件
#include <stdarg.h>
几个宏
(1). va_list 定义一个指针
用来定义一个表示参数表中各个参数的变量,即定义了一个指向参数的指针, 用于指示可选的参数.
如:va_list ap;
(2). va_start(ap,v) 初始化指针
使参数列表指针ap指向函数参数列表中的第一个可选参数,v是位于第一个可选参数之前的固定参数, 或者说最后一个固定参数.通常用于指定可变参数列表中参数的个数!
如有一va函数的声明是void va_test(char a, char b, char c, ...), 则它的固定参数依次是a,b,c, 最后一个固定参数v为c, 因此就是va_start(ap, c).
(3). va_arg(ap, type) 返回参数列表中指针ap所指的参数, 返回类型为type. 并使指针ap指向参数列表中下一个参数.返回的是可选参数, 不包括固定参数.
(4). va_end(ap) 清空参数列表, 并置参数指针arg_ptr无效.
例:
#include <iostream>
#include <stdarg.h>
using namespace std;
void simple_va_fun(int i,...); int main(int argc,char *argv[])
{
simple_va_fun();
simple_va_fun(,);
simple_va_fun(,,'a');
return ;
} void simple_va_fun(int i,...)
{
va_list arg_ptr; //定义可变参数指针
va_start(arg_ptr,i); // i为最后一个固定参数
int j=va_arg(arg_ptr,int); //返回第一个可变参数,类型为int
char c=va_arg(arg_ptr,char); //返回第二个可变参数,类型为char
va_end(arg_ptr); // 清空参数指针
printf( "%d %d %c\n",i,j,c);
return;
}
/*
输出为
100 4193388 ?
100 200 ?
100 200 a
*/
思路:
(1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针.
(2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.
(3)然后用va_arg返回第一个可变的参数,并赋值给整数j。va_arg的第二个参数是你要返回的参数的类型,这里是int型. 返回第一个可变参数后arg_ptr指向第二个可变参数,用同样的方法返回并赋值给c,类型为char类型。
(4)最后用va_end宏结束可变参数的获取。
小结:
可变参数的函数原理其实很简单,而va系列是以宏定义来定义的,实现跟堆栈相关.我们写一个可变函数的C函数时,有利也有弊,所以在不必要的场合,我们无需用到可变参数.如果在C++里,我们应该利用C++的多态性来实现可变参数的功能,尽量避免用C语言的方式来实现。
参考
http://www.jb51.net/article/41868.htm
C/C++中带可变参数的函数的更多相关文章
- 【c++】类中带默认参数的函数
反思两个问题 1. 带默认参数的函数,为何声明.定义不能同时有参数? 2. 带默认参数的函数, 为何带默认参数的参数靠后站? 上程序 #include <iostream> #includ ...
- C函数和宏中的可变参数
一:调用惯例 函数的调用方和被调用方对函数如何调用应该有统一的理解,否则函数就无法正确调用.比如foo(int n, int m),调用方如果认为压栈顺序是m,n,而foo认为压栈顺序是n, m,那么 ...
- C语言中可变参数的函数(三个点,“...”)
C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...
- [Effective JavaScript 笔记]第22条:使用arguments创建可变参数的函数
第21条讲述使用可变参数的函数average.该函数可处理任意数量的参数并返回这些参数的平均值. 如何创建可变参数的函数 1.实现固定元数的函数 书上的版本 function averageOfArr ...
- C# 中的可变参数方法(VarArgs)
首先需要明确一点:这里提到的可变参数方法,指的是具有 CallingConventions.VarArgs 调用约定的方法,而不是包含 params 参数的方法.可以通过MethodBase.Call ...
- PHP基础语法: echo,var_dump, 常用函数:随机数:拆分字符串:explode()、rand()、日期时间:time()、字符串转化为时间戳:strtotime()可变参数的函数:PHP里数组长度表示方法:count($attr[指数组]);字符串长度:strlen($a)
PHP语言原理:先把代码显示在源代码中,再通过浏览器解析在网页上 a. 1.substr; //用于输出字符串中,需要的某一部分 <?PHP $a="learn php"; ...
- 【转】C,C++中使用可变参数
可变参数即表示参数个数可以变化,可多可少,也表示参数的类型也可以变化,可以是 int,double还可以是char*,类,结构体等等.可变参数是实现printf(),sprintf()等函数的关键之处 ...
- C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数
在定义可变参数的函数之前,先来理解一下函数参数的传递原理: 1.函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈. 2.参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在 ...
- c 可变参数 定义可变参数的函数
定义可变参数的函数,需要在stdarg.h头文件中定义的va_list类型和va_start.va_arg.va_end三个宏. 定义可变参数函数 va_list ap; //实际是定义一个指针va ...
随机推荐
- kbmMW 5.07.00试用笔记
在kbmMW 5.06.20试用笔记中遇到的问题,在这个版本中,基本都解决了.但还是发现修正后存在的小问题及新问题: 1.Resolve返回值错误 当提交的ClientQuery是执行一条sql语句, ...
- Appium环境搭建过程中遇到的问题及解决办法
一.[Error: Could not detect Mac OS X Version from sw_vers output: '10.12.6'] 解决办法: 1.vi /Applications ...
- API/SPI可扩展设计原则(转)
API/SPI可扩展设计原则 博客分类: [设计体系]架构模式 API/SPISPISPI原则JAVA SPISPI机制 写本篇主要是用来后面写一篇可扩展性软件设计打好基础(苦于找不到一篇关于API ...
- RESTful Web Service 架构
特点:简单,可靠,高效,跨平台和跨语言 含义: Web Service 简单来说是指提供给不同设备通过互联网(一般使用 HTTP 协议)进行通信和交换数据的一种服务.RESTful Web Servi ...
- 微软Power BI 每月功能更新系列——5月Power BI 新功能学习
Power BI Desktop 5月份功能摘要 本月Power BI Desktop除了许多报表功能的更新,Power BI对条件格式进行了重大改进,可以对报表的任何字段(包括字符串和日期)进行条件 ...
- 2.28 查看webdriver API
2.28 查看webdriver API(带翻译) 前言 前面都是点点滴滴的介绍selenium的一些api使用方法,那么selenium的api到底有多少呢?本篇就教大家如何去查看seleni ...
- Unity跳转场景进度条制作教程(异步加载)
Unity跳转场景进度条制作 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- Vue.js学习使用心得(三)
一.计算属性 计算属性关键词: computed <body> <div id="app"> <p>原始字符串: {{ message }}&l ...
- SQLI DUMB SERIES-1
less-1 (1) 可以看到提示输入ID,而且less-1题目也有提到GET,因此试试以下操作: http: 结果: http: 结果: 现在可知,“ ' ”并没有被过滤,因此可以进行以下操作: h ...
- NFS相关、NFS服务端安装配置、exportfs命令、nfs客户端的问题
1.NFS (network file system,基于RPC协议) 2.NFS服务端安装配置安装服务端:yum install nfs-utils rpcbind -y安装客户端:yum inst ...