zoukankan      html  css  js  c++  java
  • 读书笔记:c语言标准库

    · 变长参数(stdarg.h)

      变长参数是c语言的特殊参数形式,例如如下函数声明:

    int printf(const char * format,...);
    

      如此的声明表明,printf函数除了第一个参数类型为const char*之外,其后可以追加任意数量、任意类型的参数。

      在函数实现部分,可以使用stdarg.h里的多个宏来访问各个额外的参数:假设lastarg是变长参数函数的最后一个具名参数(printf里的format),那么在函数内容定义类型为va_list的变量:

    va_list ap;
    

      该变量以后将会依次指向各个可变参数,ap必须用宏va_start初始化一次,其中lastarg必须是函数的最后一个具名的参数。

    va_start(ap,lastarg);
    

      以后,可以使用va_arg宏来获取下一个不定参数(假设已知其类型为type):

    type next = va_arg(ap, type);
    

      在函数结束前,还必须用宏va_end来清理现场。

    整理:

      va_list  实际是一个指针,用来指向各个不定参数。由于类型不明,因此这个va_lish以void *或者char *为最佳选择;

      va_start 将va_list定义的指针指向函数的最后一个参数后面的位置,这个位置就是第一个不定参数;

      va_arg   获取当前不定参数的支,并根据当前不定参数的大小将指针指向下一个参数;

      va_end  将指针清0。

      按照以上思路,va系列宏的一个最简单的实现就可以得到如下:

    #define va_list char*
    #define va_start (ap,arg)  (ap = (va_list)&arg + sizeof(arg))
    #define va_arg(ap,t)  (*(t*)((ap+=sizeof(t) - sizeof(t)))
    #define va_end(ap)  (ap = (va_list)0)
    

      

    经验:

      在很多时候,我们希望在定义宏的时候也能够像printf函数一样可以使用边长参数,即宏的参数可以是任意个,这个功能可以由编译器的边长参数宏来实现。在GCC编译器下,边长参数宏可以使用“##”宏字符串链接操作实现,比如:

    #define printf(arg...) fprintf(stdout,##args)
    

      而在MSVC下,可以通过__VA_ARGS__这个编译器内置宏,比如:

    #define printf(...) fprintf(stdout,__VA_ARGS__)
    

      

  • 相关阅读:
    Ie console未定义
    jquery bind和live区别
    php insert 空
    ie8及以下不支持getElemlentsByClassName
    jquery ajax parseerror
    你的灯亮着吗——发现问题的真正所在(摘录)
    转:getElementById引起的jQuery的选择器bug
    JS判断是否为数字、JS判断是否为整数、JS判断是否为浮点数
    Microsoft .NET Framework 4 (Standalone Installer)
    Not enough memory is available to complete this request
  • 原文地址:https://www.cnblogs.com/Eric-scratch-paper/p/5027703.html
Copyright © 2011-2022 走看看