zoukankan      html  css  js  c++  java
  • c函数中传递可变参数:va_list,va_start,va_arg,va_end

    可变参数函数就是输入的参数个数是可变的

    最经典的是printf和scanf,这两个函数的声明如下:

    1 int printf(const char *format, ...);
    2 int scanf(const char *format, ...);

    这两个函数声明中省略号(...)表示任意个数的参数

    函数的数据是存放于栈中的,那么给一个函数传递传递参数的过程就是将函数的参数从右向左逐次压栈,例如:

    func(int i, char c, doube d)

    这个函数传递参数的过程就是将d,c,i逐次压到函数的栈中,由于栈是从高地址向低地址扩展的,所以d的地址最高,i的地址最低。

    典型的写法如下:

    1 void func(char *fmt, ...){
    2       va_list ap;
    3       va_start(ap, fmt);
    4       va_arg(ap, int);
    5       va_end(va);      
    6 }

      这里ap是一个指针,指向参数的地址。

      va_start()让ap指向函数的最后一个确定的参数(声明程序中是fmt)的地址。

      va_arg()根据ap指向的地址和第二个参数所确定的类型,将这个参数的中的数据提取出来,作为返回值,同时让ap指向下一个参数。

      va_end()让ap这个指针指向0。

    关于这三个参数实现的宏可以参看下面的实现:

    1 #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
    2 #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
    3 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数的值
    4 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效

    以下为编译PL0语言的SET.c源码中的createset()函数,在此函数中就是用了可变长参数:

     1 void setinsert(symset s, int elem)
     2 {
     3     snode* p = s;
     4     snode* q;
     5 
     6     while (p->next && p->next->elem < elem)
     7     {
     8         p = p->next;
     9     }
    10     
    11     q = (snode*) malloc(sizeof(snode));
    12     q->elem = elem;
    13     q->next = p->next;
    14     p->next = q;
    15 } // setinsert
    16 
    17 symset createset(int elem, .../* SYM_NULL */)
    18 {
    19     va_list list;
    20     symset s;
    21 
    22     s = (snode*) malloc(sizeof(snode));
    23     s->next = NULL;
    24 
    25     va_start(list, elem);
    26     while (elem)
    27     {
    28         setinsert(s, elem);
    29         elem = va_arg(list, int);
    30     }
    31     va_end(list);
    32     return s;
    33 } // createset
  • 相关阅读:
    Transcation And Lock--SQL SERVER 事务隔离级别
    Transaction And Lock--常用的查询事务和锁的语句
    使用shell读取文本文件发送到kafka
    VIM打开shell脚本中文乱码解决
    shell中日期操作
    oozie常见错误问题
    error: No implicit Ordering defined for Any
    启动mysql时显示:/tmp/mysql.sock 不存在的解决方法
    mysql中创建用户和赋权限
    (转)maven3.3.9编译oozie4.3.0
  • 原文地址:https://www.cnblogs.com/tenjl-exv/p/10004365.html
Copyright © 2011-2022 走看看