定义不定参数函数,要用到下面这些宏:

  • va_start(ap, farg): 初始化一个va_list变量ap,farg是第一个形参
  • va_arg(ap, type): 获取(下)一个type类型的参数
  • va_end(ap): 结束使用ap

C语言里编写不定参数函数的形式是这样的:

#include <stdarg.h>
int sum(int cnt,...) {
int sum = 0;
int i;
va_list ap;
va_start(ap, cnt);
for(i = 0; i < cnt; ++i)
sum += va_arg(ap, int);
va_end(ap);
return sum;
}

定义不定参数函数,要用到下面这些宏:

  • va_start(ap, farg): 初始化一个va_list变量ap,farg是第一个形参
  • va_arg(ap, type): 获取(下)一个type类型的参数
  • va_copy(ap): 用于复制参数列表
  • va_end(ap): 结束使用ap
    这些宏定义一般在stdarg.h里。
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )

注意: 上面这些宏定义会因不同的系统和不同的处理器架构而不同

_INTSIZEOF宏
_INTSIZEOF这个宏的位运算意义比较难理解,乍一看以为是表示多少个int型的长度,其实它运算出来的结果是按照int型对齐后的长度。比如int型为4个字节,_INTSIZEOF(1)、_INTSIZEOF(2)、_INTSIZEOF(3)、_INTSIZEOF(4)的结果都是4,_INTSIZEOF(5)、_INTSIZEOF(6)、_INTSIZEOF(7)、_INTSIZEOF(8)的结果都是8,这正是x86架构CPU下的参数传递方式,32位即4字节对齐。

几个注意事项

  • 不定参数的函数至少要有一个固定的参数,因为要用它来初始化va_list,比如上面代码中sum函数的cnt参数,同时它也表明了传递的参数的个数。

常用方式

不定参数函数最常用来格式化字符串,一个比较常见的场景是我们想输出一些log消息,但又不能直接在控制台输出,需要自己写一个log函数来格式化log消息并输出。这时我们可以用vsprintf函数:

void log(const char *format, ...) {
char buf[MAX_BUF_SIZE];
va_list ap;
va_start(ap, format);
vsprintf(buf, format, ap);
OUTPUT(buf);
}

vsprintf函数的前两个参数和sprintf的前两个参数意义相同,只不过后面的不定参换成了va_list类型的参数列表,这正是让我们用来定义自己的格式化函数的。

https://www.cnblogs.com/luzhlon/p/7087080.html

C++传递不定参函数的更多相关文章

  1. Golang函数-不定参函数

    Golang函数-不定参函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  2. go基础之不定参函数

    指定类型参数 任意类型参数的变参 go语言同其他编程一样也提供了对变参函数的支持.本文简单讲解一下go中变参函数的使用方法. 指定类型参数 不定参数是指函数传入参数的个数为不确定数量,个数需要在调用的 ...

  3. iOS实现传递不定长的多个参数

    我们在使用苹果官方的文档的时候会发现可传不定数的参数例如: // [[UIAlertView alloc]initWithTitle:<#(nullable NSString *)#> m ...

  4. c++不定参数函数

    不定参数当年做为C/C++语言一个特长被很多人推崇,但是实际上这种技术并没有应用很多.除了格式化输出之外,我实在没看到多少应用.主要原因是这种技术比较麻烦,副作用也比较多,而一般情况下重载函数也足以替 ...

  5. 不定参数函数原理以及实现一个属于自己的printf函数

    一.不定参数函数原理 二.实现一个属于自己的printf函数 参考博文:王爽汇编语言综合研究-函数如何接收不定数量的参数

  6. def 函数的不定长函数

    *args 不定长函数传值可直接传,也可以拆包传,参数默认为元组: 参数为字典的时候:

  7. Python不定参数函数

    1. 元组形式 def test1(*args): print('################test1################') print(type(args)) print(arg ...

  8. 定时器(setTimeout/setInterval)调用带参函数失效解决方法

    也许你曾碰到过这样的问题,不管是setInterval()还是setTimeout(),当code参数里放一个带参函数时,定时器都会失效,看下面这个例子: function test(str){ al ...

  9. js addEventListener调用传参函数

    先看这段代码 function abc(key){ console.log(key); } for(let i=0;i<oInput.length;i++){ oInput[i].addEven ...

随机推荐

  1. 前端与算法 leetcode 125. 验证回文串

    目录 # 前端与算法 leetcode 125. 验证回文串 题目描述 概要 提示 解析 解法一:api侠 解法二:双指针 算法 传入测试用例的运行结果 执行结果 GitHub仓库 查看更多 # 前端 ...

  2. URL中出现了%E2%80%8E(Zero-Width Space)

    下面两个url地址,看起来是一样的,但是粘贴到记事本里会发现一个多出了很长的空格 url: '/secure​/Dishes/GetList', url: '/secure/Dishes/GetLis ...

  3. 使用benchmarkSQL测试数据库的TPCC

    压力测试是指在MySQL上线前,需要进行大量的压力测试,从而达到交付的标准.压力测试不仅可以测试MySQL服务的稳定性,还可以测试出MySQL和系统的瓶颈. TPCC测试:Transaction Pr ...

  4. 不同路径II --动态规划

    一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”). 现在考虑网 ...

  5. windows2008 开启SNMP服务

    现在很多企业和公司管理服务器时都是通过网络监控软件对服务器的状态进行监控,在监控的时候大多是通过SNMP协议(简单网络管理协议)进行的,那么在我们的服务器端就需要开启此项服务,并进行简单的设置. 以下 ...

  6. [個人紀錄] windows form , usercontrol design 模式不見

    windows form 跟 usercontrol 都變成cs檔 無法點擊進入設計模式 <Compile Include="Form1.cs"/> <Compi ...

  7. Jenkins首次进入的一些设置及配置

    1.将Jenkins显示页面修改为中文环境 首先安装中文的插件:在manage Jenkins-Manage Plugins-可选插件 下载完成之后,在系统设置里边,修改为中文格式:manage Je ...

  8. [C++] 初始化 vs 赋值

  9. jQuery---jq操作标签文本(html(),text()),jq操作文档标签(插入,删除,修改),克隆,,jq操作属性,jq操作class属性,jq操作表单value,jq操作css,jq操作盒子(重要),jq操作滚动条

    jQuery---jq操作标签文本(html(),text()),jq操作文档标签(插入,删除,修改),克隆,,jq操作属性,jq操作class属性,jq操作表单value,jq操作css,jq操作盒 ...

  10. Docker 镜像,dump openjdk-alpine 镜像容器中的 jvm

    默认情况下,我们使用的都是 jre 版本的 openjdk,当容器启动卡住不动的时候,看不出来任何问题. 此时如果能 dump 就能知道线程在干啥,也能找到一些大概的问题. 此时 jre 版本的镜像就 ...