C++可变参数函数的实现方法示例

 更新时间:2020年12月7日 11:24  点击:1306

C++编程中实现可变参数函数有多种途径,本文介绍一种最常见的实现途径,即可变参数宏方法:形参生命为省略符,函数实现时用参数列表宏访问参数。

1. 可变参数宏实现变参函数

可变参数宏实现可分为以下几个步骤:

  1. 函数形参原型中给出省略符;
  2. 函数实现中声明一个va_list可变参数列表变量;
  3. 开始初始化构造va_list变量;
  4. 访问变参列表;
  5. 完成清理工作;

上述步骤的实现需要使用到四个宏:

  1. va_list
  2. void va_start(va_list ap, last_arg)
  3. type va_arg (va_list ap, type)
  4. void va_end(va_list ap)

va_list 是在C语言中解决变参问题的一组宏

void va_start(va_list ap, last_arg)

ap :是一个 va_list 类型的对象,它用来存储通过 va_arg 获取额外参数时所必需的信息。

last_arg :是最后一个传递给函数的已知的固定参数,即省略号之前的参数。

宏定义:type va_arg (va_list ap, type)

该宏用于变参数函数调用过程中,type是当前参数类型,调用该宏后,ap指向变参数列表中的下一个参数,返回ap指向的参数值,是一个类型为type的表达式。 ap是arg_ptr参数指针之意。

void va_end(va_list ap)

允许使用了 va_start 宏的带有可变参数的函数返回。如果在从函数返回之前没有调用 va_end,则结果为未定义。
这些宏在头文件stdarg.h中声明定义。因此使用时需要包含该头文件。

下面给出用法示例:

#include <stdarg.h>

//可变参数函数sum(),求任意个数整数的和。

//Step1: 函数形参原型中给出省略符
int Sum(int count, ...);

int Sum(int count, ...) {
 //Step2: 函数实现中声明一个va_list可变参数列表变量;
 va_list ap;
 //Step3: 开始初始化构造va_list变量, 第二个参数为最后一个确定的形参
 va_start(ap, count);
 int sum = 0;
 for(int i = 0; i < count; i++) {
  //读取可变参数,的二个参数为可变参数的类型
  sum += va_arg(ap, int);
 }
 //清理工作
 va_end(ap);
 return sum;
}

实际中使用可变参数宏实现C++可变参数函数编程,还要注意一下几点:

  • 函数原型中省略号必须在参数列表的末尾:也就是说,在函数原型中参数列表省略号的右边不能再出现确定参数;
  • 试用完成是用va_end做清理工作步骤不可缺少,否则可能导致内存或资源泄漏;
  • va_list在一次访问中不能后退,但可以多次构造va_list多次访问;

2. 更安全的可变参数函数实现方法

对于上面示例代码中count传进的实参如果与后面...省略符对应的实际参数数量不一致时,可能导致函数风险。这一切完全依赖运行时的具体情况而定,很不安全。

另一种更安全的可变参数宏实现方法是利用C++的 attribute ((format()))特性来辅助可变参数的检查。

最常见的形式是有如下两个:

__attribute__((format(printf, m, n))) 
__attribute__((format(scanf, m, n)))

其中参数m与n的含义为:

m:第几个参数为格式化字符串(format string);

n:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几;

attributeformat属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。format属性告诉编译器,按照printf, scanf等标准C函数参数格式规则对该函数的参数进行检查。这在我们自己封装调试信息的接口时非常的有用。

format的语法格式为:

format (archetype, string-index, first-to-check)
  其中,“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。

下面给出2个示例:

一般函数:

为自己定义的一个带有可变参数的函数,其功能类似于printf:

extern void myprint(const char *format,...) attribute ((format(printf,1,2))); //m=1;n=2

extern void myprint(int l,const char *format,...) attribute ((format(printf,2,3))); //m=2;n=3

类成员函数

需要特别注意的是,如果myprint是一个函数的成员函数,那么m和n的值可有点“悬乎”了,例如:

extern void myprint(int l,const char *format,...) attribute ((format(printf, 3,4 )));

其原因是,类成员函数的第一个参数实际上一个隐身的this指针。

到此这篇关于C++可变参数函数实现的文章就介绍到这了,更多相关C++可变参数函数实现内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • php正确禁用eval函数与误区介绍

    eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
  • php中eval()函数操作数组的方法

    在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
  • C++ STL标准库std::vector的使用详解

    vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
  • Python astype(np.float)函数使用方法解析

    这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08
  • C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • Python中的imread()函数用法说明

    这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
  • 详解C++ string常用截取字符串方法

    这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • C++ 整数拆分方法详解

    整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
  • 金额阿拉伯数字转换为中文的自定义函数

    CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • PHP用strstr()函数阻止垃圾评论(通过判断a标记)

    strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • PHP函数分享之curl方式取得数据、模拟登陆、POST数据

    废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07
  • php中的foreach函数的2种用法

    Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25