可变参数列表
来源:互联网 发布:好桌道软件下载 编辑:程序博客网 时间:2024/05/29 13:14
可变参数列表的使用是很有必要的一件事情,在实现某个功能时,你可能不知道传几个参数。下面简单介绍一下可变参数列表的使用。
可变参数列表是通过宏来实现的,定义与stdarg.h头文件中。
void va_start(va_list ap, last); //va_start用来初始化参数列表t
type va_arg(va_list ap, type); //va_arg用来获取参数列表中的一个参数,类型为type。
void va_end(va_list ap); //va_end用来清理参数列表。
void va_copy(va_list dest, va_list src); //va_copy用来拷贝参数列表
下面是这些函数宏的实现
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 )
下面是宏的具体作用
va_list
typedef char * va_list; /*宏的定义把char*重命名为va_list,使得va_list定义的指针变量可以访问到未知参数列表*/
va_start
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )/*初始化参数列表 _INTSIZEOF(v)的作用是跳过最后一个已知变量v,ap取到未知参数列表的第一个参数,完成参数列表的初始化*/
va_arg
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))/*取出当前参数t是未知参数列表中参数的类型。((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))的作用是使得每次调用va_arg都能使指针自动往后移动一位,本次对本参数访问的同时,下次可以访问到下一个参数。/
va_end
#define va_end(ap) ( ap = (va_list)0 )/*清空参数列表把指向参数列表的指针置为0,达到清理参数列表的目的*/
接下来具体介绍可变参数列表的使用
1.求n 个数的平均数
#include<stdarg.h>#include<stdio.h>int Average(int n,...){ int i = 0; int sum = 0; va_list arg; //char* arg 类型重命名 va_start(arg, n); // #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) 宏的实现 // 替换后 ( arg = (char*)&n + 4 ) for (i = 0; i < n; i++) { sum += va_arg(arg, int); //#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) 宏的实现 //替换后 sum += ( *(int*)((arg += 4) - 4)) } va_end(arg); //#define va_end(ap) ( ap = (va_list)0 ) //替换后 (arg = (char*)0 ); return sum / n;}int main(){ int ave = Average(3, 1, 2, 3); printf("ave = %d\n", ave); system("pause"); return 0;}
2.求取参数部分n个里面的最大值
#include<stdarg.h>#include<stdio.h>int Max(int n, ...){ int i = 0; va_list arg; va_start(arg, n); int tmp = va_arg(arg, int); //tmp 用来保存第一个数 即-3 for (i = 0; i < n-1; i++) { int tmp1 = va_arg(arg, int); // 此时 tmp1 用来保存后面的数 ,即循环一次访问一个接下来元素 if (tmp < tmp1) { tmp = tmp1; } } return tmp;}int main(){ int max = Max(3, -3, -1, -2); printf("max = %d\n", max); system("pause"); return 0;}
3.printf函数的模拟实现
#include<stdarg.h>#include<stdio.h>#include<assert.h>void display(int n){ if (n > 9) { display(n / 10); } putchar(n % 10 + '0');}void print(char *format, ...){ assert(format != NULL); va_list arg; va_start(arg, format); while (*format) { switch (*format) { case 's': { char *ret = va_arg(arg, char*); while (*ret) { putchar(*ret); ret++; } } break; case 'c': { char ret = va_arg(arg, char); putchar(ret); } break; case 'd': display(va_arg(arg, int)); break; default: putchar(*format); break; } format++; }}int main(){ print("s ccc d.\n", "hello", 'B', 'A', 'T', 100); system("pause"); return 0;}以上就是我对可变参数列表的一些理解,有不对的地方还希望指正。
0 0
- Java可变参数列表
- 可变参数列表
- 关于可变参数列表
- 可变参数列表
- c++ 可变参数列表
- 可变参数列表
- cstdarg可变参数列表
- 可变参数列表
- java可变参数列表
- 可变参数列表
- Java 可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- /可变参数列表
- 可变参数列表
- proteus 安装及出现的问题解决
- linux消息队列
- Python实现简单的斐波拉切数列计算
- MyCnCart
- 访问局域网内SVN?花生壳内网穿透软件需三步
- 可变参数列表
- java基础系列(三)之--java字符串
- Android 改变View位置 setLeft、etRight、setTop、setBottom等在API 11以下的替代方法
- java自适应响应式 企业网站源码 SSM 生成静态化 手机 平板 PC
- centos7安装openvswitch虚拟交换机
- 位置和传感器:位置策略
- expdp中出现的错误
- java中的关键字和标识符
- 使用Docker搭建consul集群+registrator实现服务自动注册。