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)完事,还麻烦的先除,然后又乘。

  • 相关阅读:
    Objective-C入门教程03:属性(@property和@synthesize)
    iOS 开发的9个超有用小技巧
    oc关于非原子属性
    如果局部变量与实例变量同名,那么如何在局部变量的作用域内引用实例变量?
    从0开始搭建vue+webpack脚手架(一)
    ES6学习之 解构赋值
    Vue+webpack项目中实现跨域的http请求
    Vuejs核心思想学习笔记
    更改file文件上传默认CSS样式
    javascript获取style兼容性问题
  • 原文地址:https://www.cnblogs.com/ziyoudefeng/p/2689095.html
Copyright © 2011-2022 走看看