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

 更新时间:2020年12月06日 12:03:27   作者:apollo008  
这篇文章主要给大家介绍了关于C++可变参数函数的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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++可变参数函数实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现和电脑对战三子棋实例

    C++实现和电脑对战三子棋实例

    大家好,本篇文章主要讲的是C++实现和电脑对战三子棋实例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Matlab实现绘制有气泡感的网络图

    Matlab实现绘制有气泡感的网络图

    这篇文章主要介绍了如何利用Matlab实现绘制有气泡感的网络图,文中的示例代码讲解详细,对我们学习Matlab有一定的帮助,需要的可以参考一下
    2023-02-02
  • C语言数据的存储超详细讲解下篇浮点型在内存中的存取

    C语言数据的存储超详细讲解下篇浮点型在内存中的存取

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-04-04
  • C++中构造函数与析构函数的详解及其作用介绍

    C++中构造函数与析构函数的详解及其作用介绍

    这篇文章主要介绍了C++中构造函数与析构函数的详解及其作用介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C语言实现电器销售管理系统

    C语言实现电器销售管理系统

    这篇文章主要为大家详细介绍了C语言实现电器销售管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • opencv2基于SURF特征提取实现两张图像拼接融合

    opencv2基于SURF特征提取实现两张图像拼接融合

    这篇文章主要为大家详细介绍了opencv2基于SURF特征提取实现两张图像拼接融合,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • Qt QTreeWidget 树形结构实现代码

    Qt QTreeWidget 树形结构实现代码

    Qt中实现树形结构可以使用QTreeWidget类,也可以使用QTreeView类,QTreeWidget继承自QTreeView类,接下来通过本文给大家介绍Qt QTreeWidget 树形结构实现代码,需要的朋友可以参考下
    2021-11-11
  • C语言中的指针新手初阶指南

    C语言中的指针新手初阶指南

    指针是C语言的灵魂,精华之所在,指针强大而危险,用得好是一大利器,用得不好是一大潜在危害,下面这篇文章主要给大家介绍了C语言中指针的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • 基于Qt编写全能播放组件的示例代码

    基于Qt编写全能播放组件的示例代码

    这篇文章主要为大家详细介绍了如何基于Qt编写全能播放组件,可以支持ffmpeg2/3/4/5/6/Qt4/5/6,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-06-06
  • C语言程序环境编译+链接理论

    C语言程序环境编译+链接理论

    这篇文章主要介绍了C语言程序环境编译+链接理论,下面文章基于C语言的相关资料展开对编译和链接的详细介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-04-04

最新评论