可变参数列表
来源:互联网 发布:java平台是什么 编辑:程序博客网 时间:2024/04/29 18:30
在函数原型中,列出了函数期望接受的参数,但原型只能显示固定数目的参数。让一个函数在不同的时候接受不同数目的参数是不是可以呢?答案是肯定的,但存在一些限制。
#include<stdio.h>#include<stdlib.h>#include<stdarg.h>//利用可变参数列表实现加法。int add(int num, ...){ int i = 0; int sum = 0; int tmp = 0; va_list arg;//在这定义了一个char 类型的指针。 va_start(arg, num);//这个的功能是读取所有的参数,从头开始 //后读取你所给的参数个数,并且把参数放到指针中。 for (i = 0; i < num; i++) { tmp = va_arg(arg, int);//在这,起到的作用是读取所给的参数 sum += tmp; } va_end(arg);//结束读取 return sum;}int main(){ int ret = 0; ret=add(4,5,6,7,5); printf("%d", ret); system("pause"); return 0;}
要记住下面这些都封装在stdarg.h头文件中。
va_list arg这个说的就是一个char 类型的指针,并且记住地址
va_start(arg,…之前的一个参数) 读取所有的参数,从头开始后读取你所给的参数个数,并且把参数放到指针中。
va_arg (arg,类型)读取参数,挨个读取,返回这个参数的值,并且使得指向下一个可变参数。
va_end(arg) 结束读取。
*C语言中对可变参数的限制
-无法确定可变参数列表的长度。
-不能提供类型检查。
对于关键的宏进行解读
1.va_list
宏:#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
这个宏本身只是个定义,真正赋予其意义的在于下面的几个宏。
实现:实际上只是一个 char * 类型的指针,原因这里不能判定类型,所以用size为1的char类型指针会方便移动。2.va_start
宏:#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
这个宏需要两个参数,第一个是上面定义的 va_list, 第二个是可变参数列表之前的那个参数。
注意:va_start中的参数,一定要是最后一个参数,也就是…之前的那个参数,不然可能会有问题。尤其是windows和linux的函数参数入栈顺序不同,会有可移植性问题。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 )
为了更好的可读性,结束可变参数的获取。
可变参数必须从头到尾按照顺序逐个进行访问,如果你在访问几个可变参数后想半途中止,这是可以的,但是不能一开始就访问参数列表中间的参数。
另外需要注意的是,参数列表中至少需要有一个命名参数。命名参数指定了实际传递的参数数量,
接下来,来用可变参数列表实现一个超级厉害的system函数。
#include<stdio.h>#include<stdlib.h>#include<stdarg.h>#include<string.h>void go(int num, ...){ int i = 0; va_list arg; va_start(arg, num); for (i = 0; i < num; i++) { char arr[20]; strcpy(arr, va_arg(arg, char *)); printf("%s", arr); system(arr); } va_end(arg);}int main(){ go(9,"notepad","calc","tasklist","ipconfig","mspaint","write","title wuyuzhe","color 3e","pause");}
在这里通过这个超级厉害的system函数可以实现打开记事本,计算器,查看进程,查询ip,画图工具,写字本,然后让命令行程序的标题改成了wuyuzhe,还改了颜色,然后最后执行了暂停。
很好很强大的东西,可以实现很多的指令。
接下来,我们用可变参数列表,实现一个部分printf()函数的功能
print(“s ccc.\n”,”hello”,’b’,’i’,’t’);
print(char *format, …)
#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 'c': { char tmp = va_arg(arg, char); putchar(tmp); } break; case 's': { char *str = va_arg(arg, char*); while (*str) { putchar(*str); str++; } } break; default: putchar(*format); break; } format++; } va_end(arg);}int main(){ print("s ccc.\n", "hello", 'b', 'i', 't'); system("pause"); return 0;}
- Java可变参数列表
- 可变参数列表
- 关于可变参数列表
- 可变参数列表
- c++ 可变参数列表
- 可变参数列表
- cstdarg可变参数列表
- 可变参数列表
- java可变参数列表
- 可变参数列表
- Java 可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- C可变参数列表
- 可变参数列表
- /可变参数列表
- 可变参数列表
- TCP协议疑难杂症全景解析
- 《深入理解Android 卷III》第六章 深入理解控件(ViewRoot)系统
- LeetCode 86. Partition List
- C#接口的定义、特点、实现和应用
- 认识VTK工作原理
- 可变参数列表
- C++第三次上机实验-个人所得税计算器
- [J2EE框架][Debug]
- 虚幻4 主线程与渲染线程的同步。
- 编译原理课后习题答案令A,B和C是任意正规式,证明以下关系成立(A|B)*=(A*B*)*=(A*|B*)*
- Android动态加载基础 ClassLoader工作机制
- SI4463研究计划(兼STM32F0进一步加深理解)
- TextField的简单使用
- Git & Repo & Gerrit