zoukankan      html  css  js  c++  java
  • 可变参数函数总结

    可变参数函数主要是利用了三个宏,va_start, va_arg, va_end和一个类型va_list。

    先写个小例子,然后再说明这三个宏的含义。

    例:计算指定数量的值的平均值

     1 #include <stdarg.h>
     2 
     3 float
     4 average(int n_val, ...)
     5 {
     6     va_list arg; // 等价于char *arg;
     7     int count;
     8     float sum = 0;
     9     
    10     va_start(arg, n_val); // arg = &n_val + 4 (假设这里int长度是4个字节)
    11     
    12     for (count = 0; count < n_val; ++count)
    13     {
    14         sum += va_arg(arg, int); // 等价于sum += *arg; arg = arg + 4(假设这里va_arg第二个参数int类型的长度为4)
    15     }
    16     va_end(arg); // 等价于arg = 0;
    17     
    18     return sum / n_val;
    19 }

    通过上面的例子,大体上知道了va_list其实就是typedef char* va_list;(PS:我发现大部分源代码在处理类似于指针什么的类型时,都用的是char,或者char*,或者unsigned char。不知道这个是为啥,比如atoi中)

    然后是三个宏:

      va_start:该宏初始化前面设置的va_list变量,把该va_list变量设置为可变参数中第一个参数的地址

      源代码为:

    #define va_start(ap, pN) ((ap) = ((va_list) (&pN) + __va_argsiz(pN))) // _va_argsiz宏是计算参数长度的

      va_arg:源代码为

    #define va_arg(ap, t) (((ap) = (ap) + __va_argsiz(t)), *((t*) (void*) ((ap) - __va_argsiz(t)))) // 一个逗号表达式。不理解干嘛先增加ap,然后又返回ap-增加的量。直接先返回ap的值,然后再增加ap不好吗?

      va_end:源码

    #define va_end(ap)    ((void)0)

    最后把strarg.h文件中说明_va_argsiz的源码给出来,自己不是很理解这里计算大小的过程

    /*
     * Amount of space required in an argument list (ie. the stack) for an
     * argument of type t.
     */
    #define __va_argsiz(t)    \
        (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))

    之前看SGI源码时,也发现有这样计算的:即先加上要除的内容,然后-1,然后再除。 不知道这样是为了确保什么,哪位知道,不妨告知。还有,这里为啥不直接是sizeof(t)完事,还麻烦的先除,然后又乘。

  • 相关阅读:
    下载并使用ASP.NET MVC v1.0 Futures
    关于DataGridView的数据源两个值得注意的小问题
    C++网络编程(二)客户端服务器程序
    C++多态、继承的简单分析
    XML文件解析器TXml
    数组
    CTS类型系统
    光阴不会虚度
    软件的大规模生产
    微创新和山寨的关系
  • 原文地址:https://www.cnblogs.com/ziyoudefeng/p/2689095.html
Copyright © 2011-2022 走看看