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 ...
随机推荐
- Collection集合复习方法回顾
Collection集合方法: add() //添加元素 remove() //移除元素 size() //返回集合长度 ...
- java学习笔记19(Arrays类)
Arrays类: 此类包含用来操作数组的各种方法(比如升序和搜索): import java.util.Arrays; public class Demo { public static void m ...
- ecmall 基础类分析
class ECBaseApp,继承自class BaseApp,是includes/ecapp.base.php文件. 该类是一个非常重要的类,他是各个APP的应用的基础继承类.处理相关的基础应用. ...
- 转 linux常用查看硬件设备信息命令
转载自:http://blog.chinaunix.net/uid-26782198-id-3242120.html 系统 # uname -a # 查看内核/操作系统/C ...
- 用Synoptic Panel自定义基于图形的可视化控件--制作一张剧场售票统计报表
数据可视化的一大特点就是能给报表使用者带来感官上的享受.不再是枯燥的数字,而变成一个一个亮丽的图形.之前业界大神公布过一个统计Car Accidents的报表,这个Power BI Report的特点 ...
- [转]EM算法(Expectation Maximization Algorithm)详解
https://blog.csdn.net/zhihua_oba/article/details/73776553 EM算法(Expectation Maximization Algorithm)详解 ...
- Golang游戏服务器与skynet的个人直观比较
我对和GOLANG写MMO服务器的一些遐想: 1.沙盒(隔离性) SKYNET:原生LUA STATE作为沙盒, 进行服务器间隔离安全性高: 服务可以很容易的配置到不同节点之上. GO:估计用RECO ...
- JAXB性能优化
前言: 之前在查阅jaxb相关资料的同时, 也看到了一些关于性能优化的点. 主要集中于对象和xml互转的过程中, 确实有些实实在在需要注意的点. 这边浅谈jaxb性能优化的一个思路. 案列: 先来构造 ...
- 一种安装openslide的简易方法
直接百度谷歌搜索可能需要手动编译安装,能不能用通过一两句命令行的方式安装openslide?网上给出的教程确实都是通过源安装python-openslide,实际上这样安装,即使安装很多依赖库之后仍然 ...
- N!的近似值_斯特林公式
公式: N! ~= sqrt(2 * PI * n) * ((n / e) ^n) 题目类型不慌都.