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

  • 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

最新文章

  1. [MVC4]初识.NET MVC4
  2. Redis Cluster 3.0搭建与使用
  3. 深入学习:Windows下Git入门教程(下)
  4. github创建repo,本地导入git项目到github
  5. android shape(如自定义Button)
  6. OpenWrt刷机后LAN口无法连通的问题
  7. Javascript实现两张图片的延迟加载
  8. Photoshop CS4序列号过期的问题
  9. PHP文章关键词相似短尾长尾内链替换方法介绍
  10. WTL---WxWidget---MFC 何去何从
  11. MySQL的四种事务隔离级别
  12. 爬虫新手学习2-爬虫进阶(urllib和urllib2 的区别、url转码、爬虫GET提交实例、批量爬取贴吧数据、fidder软件安装、有道翻译POST实例、豆瓣ajax数据获取)
  13. ASP.NET MVC编程——错误处理与日记
  14. OO第二单元作业总结【自我反思与审视】
  15. 刷新浏览器 protractor
  16. Python序列结构--集合
  17. Codeforces1076F. Summer Practice Report(贪心+动态规划)
  18. .net环境下的缓存技术-转载!
  19. RabbitMQ理论部分
  20. VM虚拟机上在NAT模式下设置静态IP的做法

热门文章

  1. [转帖]浅谈P2P、P2C 、O2O 、B2C、B2B、 C2C的区别
  2. ElasticSearch 线程池类型分析之 ExecutorScalingQueue
  3. DELPHI网页开发神器UNIGUI的安装与演示
  4. Python 3 + Selenium 3 简单入门学习示例 126邮箱登录
  5. 「NOI2015」小园丁与老司机
  6. Java学习:单列集合Collection
  7. 重点|183道Java面试题可以说很详细了
  8. APUE之第5章——标准I/O库
  9. Dapper安装与使用
  10. 二十三、并发编程之深入解析Condition源码