打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
《OOC》笔记(3)——C语言变长参数va_list的用法

《OOC》笔记(3)——C语言变长参数va_list的用法

《OOC》笔记(3)——C语言变长参数va_list的用法

C语言中赫赫有名的printf函数,能够接受的参数数目不固定,这就是变长参数。C#里也有params这个关键字用来实现变长参数。

1 printf("Hello Mozart!");2 printf("Hello %s!", "Mozart");3 printf("%d: Hello %s!", 77, "Mozart");

用C实现一个能接受变长参数的函数

举例如下。

 1 #include <stdarg.h> 2  3 int add(const char * testString, int x, ...)  4 { 5     printf("%s\n", testString); 6     va_list list; 7     va_start(list, x);  8     int result = 0; 9 10     for(;;)11     {12         int p = va_arg(list, int);13         if(p == 0)14             break;15         result += p;16     }17     va_end(list); // cleanup , set 'lsit' to NULL18     return result;19   }20 21 /* error: ISO C requires a named argument before '...'22 void add2(...)23 {24 }25 */26 27 int main()28 {29     int result = add("test case 1: ", 1, 2, 3, 4, 5, 0);30     printf("%d\n", result);31     system("PAUSE");32     return 0;33 }34 35 /*36 This program print as follows:37 test case 1: 38 1539 */

编写使用变长参数的函数步骤如下。

  • 首先,引用stdarg.h。
  • 然后,在函数声明中用"..."表示这个函数能够使用变长参数。

注意,在"..."前面至少要有一个普通的参数。(可能非标准C不需要,不过我们还是保守一点最好)

  • 那么如何使用这些数目、类型都不确定的参数呢?

va_list类型的list变量可以遍历"..."中的参数。

用va_start()来初始化list变量。va_start()需要挨着"..."的左边那个参数名。(示例中的x)

va_arg()用于获取下一个参数值。这个参数值的类型你必须在编码时就能确定。

va_end()用于结束对list的遍历。之后你可以再次使用va_start()、va_arg()、va_end()来依次获取各个可变参数值。

 

注意事项

在add这个示例中,最后一个参数必须为0,add才能知道可变参数处理完毕。没有别的办法。也就是说,你不可能通过任何方式不借助外力就得知传进来的可变参数到底有几个。

在printf("%d, %s, %c", 1, "11", '1');函数中,printf会分析格式化参数"%d, %s, %c",它看到3个格式化输出符号,所以就认为传入了3个可变参数。如果你传入的多了或者少了,程序就可能出错。编译器无法检测这个错误。

list变量可以作为参数传递给其它函数。(如vprintf("xxx", list);)

在传递可变参数时,整型会作为int或long传递,float型会作为double传递。

va_arg()的第二个参数(示例中的int)不应太复杂。(这话很含糊)

总之,C语言中使用变长参数不是什么好的编程实践。能避免尽量避免。

 

原理是什么?

typedef char* va_list#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是在stdio.h中定义的类型。va_start、va_arg、va_end是三个宏定义。

va_start把((v的地址)+(v的长度))赋给list。根据函数调用时形参的内存布局,这样list就指向了第一个可变参数。(示例中的2)

每次调用va_arg都会获得当前参数值,并将ap指针指向下一个参数。

调用va_end会将ap重置为0。

所以这个可变参数的原理就是一个迭代器,它在函数栈的参数上移动以依次获取可变参数。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
变长参数的实现
va_list、va_start、va_arg、va_end
C语言之可变参数问题 - 欢迎阁下光临我的网络日志-safeking‘s blog - 博...
变参函数的实现
c语言中可变参数函数的设计 - C函数用法 - nlchjian
stdarg.h
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服