码迷,mamicode.com
首页 > 编程语言 > 详细

读书笔记:c语言标准库 - 变长参数

时间:2015-12-08 00:15:11      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

· 变长参数(stdarg.h)

  变长参数是c语言的特殊参数形式,例如如下函数声明:

int printf(const char * format,...);

  如此的声明表明,printf函数除了第一个参数类型为const char*之外,其后可以追加任意数量、任意类型的参数。

  在函数实现部分,可以使用stdarg.h里的多个宏来访问各个额外的参数:假设lastarg是变长参数函数的最后一个具名参数(printf里的format),那么在函数内容定义类型为va_list的变量:

va_list ap;

  该变量以后将会依次指向各个可变参数,ap必须用宏va_start初始化一次,其中lastarg必须是函数的最后一个具名的参数。

va_start(ap,lastarg);

  以后,可以使用va_arg宏来获取下一个不定参数(假设已知其类型为type):

type next = va_arg(ap, type);

  在函数结束前,还必须用宏va_end来清理现场。

整理:

  va_list  实际是一个指针,用来指向各个不定参数。由于类型不明,因此这个va_lish以void *或者char *为最佳选择;

  va_start 将va_list定义的指针指向函数的最后一个参数后面的位置,这个位置就是第一个不定参数;

  va_arg   获取当前不定参数的支,并根据当前不定参数的大小将指针指向下一个参数;

  va_end  将指针清0。

  按照以上思路,va系列宏的一个最简单的实现就可以得到如下:

#define va_list char*
#define va_start (ap,arg)  (ap = (va_list)&arg + sizeof(arg))
#define va_arg(ap,t)  (*(t*)((ap+=sizeof(t) - sizeof(t)))
#define va_end(ap)  (ap = (va_list)0)

  

经验:

  在很多时候,我们希望在定义宏的时候也能够像printf函数一样可以使用边长参数,即宏的参数可以是任意个,这个功能可以由编译器的边长参数宏来实现。在GCC编译器下,边长参数宏可以使用“##”宏字符串链接操作实现,比如:

#define printf(arg...) fprintf(stdout,##args)

  而在MSVC下,可以通过__VA_ARGS__这个编译器内置宏,比如:

#define printf(...) fprintf(stdout,__VA_ARGS__)

  

 

读书笔记:c语言标准库 - 变长参数

标签:

原文地址:http://www.cnblogs.com/Eric-scratch-paper/p/5027703.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!