时间:2021-05-20
在C语言程序编写中我们使用最多的函数一定包括printf以及很多类似的变形体。这个函数包含在C库函数中,定义为 int printf( const char* format, ...);
除了一个格式化字符串之外还可以输入多个可变参量,如:
printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s", i, s);格式化字符串的判断本章暂且不论,下面分析一下可变参数的实现细节。
运行结果如下:
book@book-desktop:~/own$ ./varlist
num:5, vl:1
in for result:1, *vl:2
in for result:2, *vl:3
in for result:3, *vl:4
in for result:4, *vl:5
可变参数列表的实现是由几个宏组成的,在文件include/stdarg.h中:
va_list 定义某个变量,内核中的定义:
typedef char *va_list;//字符指针类型va_start(ap, type) 开始获取可变参数列表中的第一个参数(...里面的第一个),也就是跳过第一个参数(即num):
#ifndef __sparc__#define va_start(AP, LASTARG) \ (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))//ap指向下一个参数,lastarg不变#else#define va_start(AP, LASTARG) \ (__builtin_saveregs (), \ AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) //跳过下第一个参数,指向第二个参数内存地址#endif//对type向上取整 取int的整 4,然后乘上int整型4的倍数#define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))va_arg(args, int) 循环获取到可变参数列表中的参数,args指向下一个参数地址,返回的则是当前参数地址
// first=va_arg(args,int)#define va_arg(AP, TYPE) \//ap指向下一个类型的参数 (AP += __va_rounded_size (TYPE), \//返回ap - sizeof(type)参数,即前一个参数 *((TYPE *) (AP - __va_rounded_size (TYPE))))//对type向上取整 取int的整 4,然后乘上int整型4的倍数#define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))最后一个va_end(ap)结束标志,可能只是在程序中作为一个可变参数列表的结束标志而已(stdarg.h里面只是仅仅定义了下,没有实现的代码部分)。
因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢,可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型.有人会问:那么printf中不是实现了智能识别参数吗?那是因为函数printf是从固定参数format字符串来分析出参数的类型,再调用va_arg的来获取可变参数的.也就是说,你想实现智能识别可变参数的话是要通过在自己的程序里作判断来实现的.另外有一个问题,因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.
如将simple可变参数该成char型指针,若存在空指针在会产生coredump
void simple(int i, ...){ va_list arg_ptr; char *s=NULL; va_start(arg_ptr, i); s=va_arg(arg_ptr, char*); va_end(arg_ptr); printf("%d %s\n", i, s); return;}可变参数为char*型,当我们忘记用两个参数来调用该函数时,就会出现core dump(Unix) 或者页面非法的错误(window平台).但也有可能不出错,但错误却是难以发现,不利于我们写出高质量的程序.
到此这篇关于C语言中可变参数的使用方法示例的文章就介绍到这了,更多相关C语言可变参数用法内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
可变参数可变参数应该最简单,在C/C++和Java等语言中都有,就是用*号来表示,例如deftestArg(*arg)你可以传入任意多个元素(包括0)到参数中,
java中的可变参数使用方法可变参数时Java1.5新增的方法,可变参数方法接收0个或者多个指定类型的参数,可变参数机制通过先创建一个数组,数组的大小为在调用位
C语言的printf函数,参数的数量可以是可变的。使用va_start和va_end实现。C++中,实现参数可变,可以用overload。如果参数数量不是很多的
本文实例讲述了C#中参数个数可变的方法。分享给大家供大家参考。具体方法如下:要实现C#中参数个数可变关键是使用params关键字。并且,可变参数只能是所有参数中
C语言中没有函数重载C++语言中有函数重载函数名相同,参数个数不同、参数类型不同、参数顺序不同例如下面就是函数重载voidsum(inta,intb){cout