可变参数列表解析
2017-12-10 17:50
134 查看
可变参数
在写c程序时,我们经常使用到printf这个函数,那么在使用这个函数时,我们给他传参吗?传几个参数?可以看一下函数原型:
可以看出,printf也是有参数的,并且可以传1个以上任意多个参数。
这就是可变参数。
举一个实例来说明:
int average(int n, ...) { va_list arg;//定义一个指针变量 int i = 0; int sum = 0; va_start(arg, n);//指向可变参数列表部分 for (i = 0; i<n; i++) { sum += va_arg(arg, int);//读取每一个参数,并且加到一起 } return sum / n; 4000 va_end(arg);//结束读取 } int main() { int a = 1; int b = 2; int c = 3; int avg = average(3, a, b, c); printf("avg = %d\n", avg); system("pause"); return 0; }
对于关键宏的解读
此处使用的宏都在stdarg.h头文件中包含。1.va_list
宏:#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
实现:实际上只是一个 char * 类型的指针。
2.va_start
宏:#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
这个宏需要两个参数,第一个是上面定义的 va_list, 第二个是可变参数列表之前的那个参数。
注意:va_start中的参数,一定要是已知的最后一个参数,即就是…之前的那个参数。
3.va_arg
宏:#define va_arg(ap,t) ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
同样有两个参数,第一个是前面已经初始化好的 va_list,第二个是类型,比如这里可变参数列表的第一个参数是int类型,那么就传int。
4.va_end
宏:#define va_end(ap) ( ap = (va_list)0 )
为了更好的可读性,结束可变参数的获取。
可变参数的限制
注意可变参数必须从头到尾访问。可以在访问几个可变参数之后终止,但不能从一开始就访问参数列表中间的参数。
参数列表中至少要有一个已知的命名参数,不能一个都没有,否则无法使用va_start。
这些宏是无法直接判断实际存在参数的数量。
并且宏也无法判断每个参数的类型。
实现printf函数
再了解了可变参数列表之后,可以实现一个我们自己的printf函数。#include<stdio.h> #include<stdlib.h> #include<stdarg.h> void print(char *format,...) { va_list(arg); va_start(arg, format); while (*format) { switch (*format) { case 's': { char *str = va_arg(arg, char*); while (*str) { putchar(*str); str++; } } break; case 'c': { char c = va_arg(arg, char); putchar(c); } break; default: break; } format++; } va_end(arg); } int main() { print("s cccccc d.\n","hello",'\t','w','o','r','l','d',100) system("pause"); return 0; }
相关文章推荐
- sudo gedit修改环境变量出错No protocol specified
- 设计模式--适配器模式
- UE4踩坑总结
- mybatis 一级缓存
- js预处理和闭包
- ZYNQ+Vivado2015.2系列(七)软硬件联合Debug观察AXI总线读、写时各信号的时序
- [work]tensorflow Windows 安装
- [ubuntu]安装配置jdk和eclipse新建 工程
- CF 155C. Hometask 思维+模拟.
- Dubbo第一章:Dubbo-admin编译和Dubbo简单入门
- Django项目-数据库,模型创建
- < meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />的意义
- VSCode+golang 安装配置
- 各种彩色模型转换的方法
- Struts2系统拦截器struts-default
- targan求LCA
- 虚幻4结合worldmachine制作地形
- IP地址、子网掩码相关知识
- Scrapy爬虫入门教程十三 Settings(设置) settings from_crawler
- nyist 737