浅析可变参数列表
2016-04-18 16:55
204 查看
可不参数列表可以让函数在不同时候接受不同数目的参数。
C语言可变参数列表使用总可分为4个部分.
1、va_list
首先,我们先来看一下它的定义:
#ifdef _M_ALPHA
typedef struct{
char*a0;/*pointertofirsthomedintegerargument*/
intoffset;/*byteoffsetofnextparameter*/
}va_list;
#else
typedef char*va_list;#endif
就我们所知,typedef将va_list定义成了一个char*类型;
所以在使用va_list时,
va_list arg;//作用就是将arg定义成了一个char类型的指针
2、va_start
va_start是一个宏,它的作用是获取第一个参数的地址,即括号内的最左边第一个参数
的地址。
它的定义为:
#defineva_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v))
使ap指向第一个参数的地址。(ap即为va_list所定义的指针)
这里使用到了一个_INTSIZEOF,注意,它也是一个宏,作用是获取目标参数v所占用空间的
长度大小。
它在这里起到了一个初始化的作用。具体的使用在下面会举例。
3、va_arg
va_arg是一个宏,它的作用是向后访问。定义为:
#defineva_arg(ap,t)(*(t*)((ap+=_INTSIZEOF(t))-_INTSIZEOF(t)))
每次调用,它先获取当前的参数,并使指针ap指向下一个参数。
(至于这里为什么先使ap加上一个_INTSIZEOF(t), 又减去一个_INTSIZEOF(t)。从而起到是ap
指针向后移动的作用,博主尚未弄明白)。
4、va_end
类型也是宏,作用为清空 va_list所定义的可变参数列表。
#define va_end(ap) (ap=(va_list)0)
5、可变参数列表有几个限制条件
<1> 函数的参数至少含有一个。
<2> va_start无法计算参数的个数。
<3> 无法直接知道参数类型。
<4> va_arg如果给定了错误的类型,结果不可预料。
下面来看一个例子
执行后结果应为:
C语言可变参数列表使用总可分为4个部分.
1、va_list
首先,我们先来看一下它的定义:
#ifdef _M_ALPHA
typedef struct{
char*a0;/*pointertofirsthomedintegerargument*/
intoffset;/*byteoffsetofnextparameter*/
}va_list;
#else
typedef char*va_list;#endif
就我们所知,typedef将va_list定义成了一个char*类型;
所以在使用va_list时,
va_list arg;//作用就是将arg定义成了一个char类型的指针
2、va_start
va_start是一个宏,它的作用是获取第一个参数的地址,即括号内的最左边第一个参数
的地址。
它的定义为:
#defineva_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v))
使ap指向第一个参数的地址。(ap即为va_list所定义的指针)
这里使用到了一个_INTSIZEOF,注意,它也是一个宏,作用是获取目标参数v所占用空间的
长度大小。
它在这里起到了一个初始化的作用。具体的使用在下面会举例。
3、va_arg
va_arg是一个宏,它的作用是向后访问。定义为:
#defineva_arg(ap,t)(*(t*)((ap+=_INTSIZEOF(t))-_INTSIZEOF(t)))
每次调用,它先获取当前的参数,并使指针ap指向下一个参数。
(至于这里为什么先使ap加上一个_INTSIZEOF(t), 又减去一个_INTSIZEOF(t)。从而起到是ap
指针向后移动的作用,博主尚未弄明白)。
4、va_end
类型也是宏,作用为清空 va_list所定义的可变参数列表。
#define va_end(ap) (ap=(va_list)0)
5、可变参数列表有几个限制条件
<1> 函数的参数至少含有一个。
<2> va_start无法计算参数的个数。
<3> 无法直接知道参数类型。
<4> va_arg如果给定了错误的类型,结果不可预料。
下面来看一个例子
// 利用可变参数列表模拟printf函数输出字符串,字符。 #include<stdio.h> #include<stdarg.h> void print(const char *format,...) { va_list arg; //定义arg(char类型)指针 va_start(arg,format); //对arg进行初始化,使其指向第一个参数 while(*format) { switch(*format) //因为有字符,字符串两种情况,所以这里用switch比较好。 { case's': //若读取到为s,则为字符串 { char *str=va_arg(arg,char*); /*注意,这里要用一个局部变量对va_arg(arg,char*)进行一次保存, 因为每次调用一次va_arg(arg,char*),它都会向后移动, 若,直接 puts(va_arg(arg,char*))会输出下一个参数的值。*/ puts(str); } break; case'c': //若为猜,则为字符。 { char tmp=va_arg(arg,char);//若此处char不行,换用int 试一下。博主遇到过这种情况,尚未明白。 //同样用tmp进行一次保存。 /*注意,va_arg不会辨别参数的类型,该参数是什么类型,va_arg括号中 第二个位置就写什么类型,不要写错,不热会造成不可预料的后果。这也是 可变参数列表的一个限制条件。*/ putchar(tmp); } break; default: /*当switch所有情况列举完后,用default分支结尾。即使真的不需要default, 也应该保留语句 ,具体作用自己网查*/ putchar(*format); break; } format++; } va_end(arg);//最后清空va_list定义的arg } int main() { print("s ccc.\n","hello",'b','i','t'); return 0; }
执行后结果应为:
相关文章推荐
- 个人工作总结1
- 设置mini2440的静态IP
- 8皇后
- ionic入门教程第九课-开始动手做项目吧!ion-nav-bar、ion-nav-buttons、ion-tabs
- Protobuf语言指南
- 面试中问到SpringMVC与struts的区别
- Hibernate---O/R Mapping
- MongoDB ReplacaSet & Sharding集群安装 配置 和 非集群情况的安装 配置 -摘自网络
- json字符串换成json数据类型
- 动态规划解最长公共子序列问题
- php代码优化
- Android Studio 获取SH1和MD5的方法
- PostgreSQL 序列(SEQUENCE)
- Android实现搜索功能并本地保存搜索历史记录
- 在c#程序中初步使用redis
- C# “配置系统未能初始化” 异常解决
- 权限控制框架 shiro
- Android基础控件 -- EditText
- 人工智能60年:图灵的在天之灵,安息吧!
- 安卓自定义View之贝塞尔曲线简单使用