博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C/C++ 实现可变参数
阅读量:5807 次
发布时间:2019-06-18

本文共 1821 字,大约阅读时间需要 6 分钟。

  hot3.png

引言
C语言支持可变参数,即参数个数不固定,典型的函数如printf, scanf等可以接受数量不定的参数。
如,printf("one parameter");printf("two parameter: %d", a);printf("three parameter: %d, %s", a, s);
上面三个printf分别接收1,2,3个参数。来看一下printf的原型:
#include <stdio.h>
int printf(const char *format, ...);
由此可以看出,printf除接收一个固定的参数format以外,后面的参数用"..."表示,即"..."表示可以接受0个或多个参数。
一个类型三个宏
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
va_list类型大部分场合下为char *,即typedef char * va_list;
va_start 接收两个参数,一个是va_list类型的变量,一个是省略号前最后一个有名字的参数,该宏实际做了初始化工作。
va_arg 接收两个参数,一个是初始化后的va_list变量,一个是返回的参数类型,每一次调用都会返回下一个参数。
va_end 接收va_list变量,进行清理工作。
实现可变参数函数很简单,三步走就可以:va_start初始化,va_arg取参数,va_end清理现场。
例子

下面程序实现了两个可变参数函数,maxInt 接受n个整数,返回最大的数;maxStr接受n个字符串,返回最长的那个。

#include 
#include
using namespace std;int maxInt(int num, ...);std::string maxStr(int num, ...);int main(){ int n = maxInt ( 5, 5, 6 ,3 ,8 ,5); cout << n; std::string m = maxStr(5, "a", "ab", "abc", "abcd", "abcde"); std::cout << m << std::endl; return 0;}int maxInt(int num, ...){ int m = 0; va_list ap; va_start(ap, num); for ( int i= 0; i< num; i++ ) { int t = va_arg (ap, int); if ( t > m ) { m = t; } } va_end (ap); return m;}std::string maxStr(int num, ...){ std::string ret; va_list ap; va_start(ap, num); for(int i = 0; i < num; i++) { std::string l_tmp = va_arg(ap, char*); std::cout << "get param: " << l_tmp << std::endl; if(l_tmp.length() > ret.length()) ret = l_tmp; } va_end(ap); return ret;}
其他
1.可变参数函数必须要有一个固定参数吗?
不一定,有的环境下va_start只接收一个va_list类型参数,这种情况下可变参数函数或许可以没有参数,没有验证过。
2.关于va_copy
va_copy 原型是void va_copy(va_list dest, va_list src);提供了两个va_list拷贝功能。其不是标准C提供的,而是在C99中定义的,可以选择使用。

转载于:https://my.oschina.net/renhc/blog/113034

你可能感兴趣的文章
CentOS 6.6 FTP install
查看>>
C#------判断btye[]是否为空
查看>>
图解Ajax工作原理
查看>>
oracle导入导出小记
查看>>
聊一聊log4j2配置文件log4j2.xml
查看>>
NeHe OpenGL教程 第七课:光照和键盘
查看>>
修改上一篇文章的node.js代码,支持默认页及支持中文
查看>>
Php实现版本比较接口
查看>>
删除设备和驱动器中软件图标
查看>>
第四章 TCP粘包/拆包问题的解决之道---4.1---
查看>>
html语言
查看>>
从源码看集合ArrayList
查看>>
spring-boot支持websocket
查看>>
菜鸟笔记(一) - Java常见的乱码问题
查看>>
我理想中的前端工作流
查看>>
记一次Git异常操作:将多个repository合并到同一repository的同一分支
查看>>
CodeIgniter 3.0 新手捣鼓源码(一) base_url()
查看>>
Chrome 广告屏蔽功能不影响浏览器性能
查看>>
vSphere 6将于2月2日全球同步发表
查看>>
Android状态栏实现沉浸式模式
查看>>