zoukankan      html  css  js  c++  java
  • c的可变参数(va_arg,va_list,va_start,va_end)

    首先是头文件. <stdarg.h>

    其次, 我们的目的是实现支持变长参数的函数, 但并不是说,这个函数参数可以全都是变的. 不行. 函数的参数列表中, 一定至少要有一个有name的参数. 比如printf, 它的定义是printf(const char * restrict format, ...);也是有restrict format这个有name的参数的. 变参正如printf显示的那样, 是...

    好了, 怎么用呢. 我们拿一个网上博客的例子. 出处是深入C语言可变参数(va_arg,va_list,va_start,va_end)

    #include <stdio.h>
    #include <stdarg.h>
    
    void print_args(int count, ...);
    
    int main(int argc, char* argv[]) {
    	print_args(5,1,2,3,4,5);
    	return 0; 
    }
    
    void print_args(int count, ...) {
    	int i, value;
    	va_list arg_ptr;
    	va_start(arg_ptr, count);
    	for(i=0; i<count; i++) {
    		value = va_arg(arg_ptr,int);
    		printf("position %d = %d
    ", i+1, value);
    	}
    	va_end(arg_ptr);
    }
    

    首先看函数的定义, 有一个有name的参数count, 除此之外就是变参...
    要获得变参, 首先需要定义一个va_list类型的变量, 这里是va_list arg_ptr;. 这个类型的变量, 之后会遍历获取到所有的参数, 这个变量我们会一直用, 一直到参数解析完毕.
    但这个变量使用前必须初始化, 我们看到是va_start(arg_ptr, count);, 这个函数实际上是一个宏. 它需要两个参数, 第一个是va_list类型的遍历变量, 第二个参数是这个函数最后一个有name的参数, 这里就是count. 但是va_start的作用是什么呢?

    The macro va_start initializes ap to point to the first unnamed argument.
    让它指向第一个unnamed的参数.
    好了, 那么怎么获得变参呢? 这就是value = va_arg(arg_ptr,int);, 第一个参数自然是va_list类型, 第二个参数是指定类型, 这样才知道它占的内存大小, 才知道它占了多少, 下一步该到内存什么位置. 返回就会返回int类型的. 这个va_arg应该也是宏.
    最后必须在函数返回前调用va_end, K&R是这么说的:
    Finally, va_end does whatever cleanup is necessary.

    好了再总结使用要点:

    • 头文件是<stdarg.h>
    • 先定义va_list变量, 然后va_start它, 第二个参数是最后一个named参数
    • va_arg(va_list变量, 类型)解析参数, 返回就是我们调用的参数.
    • 最后用va_end释放va_list变量.
  • 相关阅读:
    读书笔记 之《Thinking in Java》(对象、集合、异常)
    ArrayList 和 LinkedList的执行效率比较
    Hybris CronJob.
    C# 中的treeview绑定数据库(递归算法)
    identity_insert---实验性插入大批量数据和分页存储过程
    SQL Server 存储过程
    PL/SQL 在64位机上不能使用的问题解决
    登陆Oracle11g的企业管理器
    SQL在oracle和SQLserver将查询结果创建为新表的不同之处
    介绍一下内联、左联、右联
  • 原文地址:https://www.cnblogs.com/Tokubara/p/14036688.html
Copyright © 2011-2022 走看看