zoukankan      html  css  js  c++  java
  • C语言可变长參数实现原理


    微博:http://weibo.com/u/2203007022              


     (1)      C语言可变參数

    我们能够从C语言的printf得出可变參数的作用。printf函数的原型例如以下:
    int printf ( const char * format, ... );
    通过使用可变个数參数,就是传入的參数个数是可变的,如printf须要依据format实參传入多个实參。

    (2)      C语言可变參数的使用

    以下一个函数myprintf是自己实现的比較简单的printf函数。不完整可是能够说明可变參数的使用方法。

    /*
     * Author: guojun07
     */
    
    #include <stdio.h>
    #include <stdarg.h>
    #include <unistd.h>
    #include <string.h>
    
    void myprintf(char *format, ...) {
      va_list ap;
      int pos = 0;
      int int_val = 0;
      float f_val;
      char buf[64];
      memset(buf, 0, 64);
      // 得到全部的參数放到下一个list中ap中
      va_start(ap, format);
      while (format[pos] != '') {
        // 推断'%'。表示要得到下一个參数
        if (format[pos] == '%') {
          pos ++;
          switch(format[pos]) {
            case 'd':
            case 'u':
              // 得到ap中的下一个參数
              int_val = va_arg(ap, int);
              sprintf(buf, "%d", int_val);
    	  // 将数据写到标准输出
              write(STDOUT_FILENO, buf, strlen(buf));
              memset(buf, 0, 64);
              pos ++;          
    	  break;
            case 'f':
              // 得到ap中的下一个參数
              f_val = (float)va_arg(ap, double);
              sprintf(buf, "%f", f_val);
    	  // 将数据写到标准输出
              write(STDOUT_FILENO, buf, strlen(buf));
              memset(buf, 0, 64);
              pos ++;
              break;
            default:
              break;
          }
        } else {
          write(STDOUT_FILENO, &(format[pos]), 1);
          pos ++;
        }
      }
    }
    
    int main(void){
      myprintf("this is a testing, i = %d, u = %u, f = %f
    ", -1, 5, 0.2);
      return 0;
    }
    
    程序的数据结果例如以下:
    guojun8@guojun8-desktop:~/test/valist$ ./main
    this is a testing, i = -1, u = 5, f = 0.200000

    (3)      实现

    以下介绍C语言可变长度參数的实现。事实上现与一个数据结构(va_list)和三个宏(va_start, va_end, va_arg)相关,从源代码中能够看到这些实现以下的来自linux内核源代码中的文件(include/acpi/platform/acenv.h)
    #ifndef _VALIST
    #define _VALIST
    typedef char *va_list;
    #endif        /* _VALIST */
     
    /*
    * Storage alignment properties
    */
    #define  _AUPBND                (sizeof (acpi_native_int) - 1)
    #define  _ADNBND                (sizeof (acpi_native_int) - 1)
     
    /*
    * Variable argument list macro definitions
    */
    #define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
    #define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
    #define va_end(ap)              (void) 0
    #define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

     a)         va_list

    从实现中能够看出va_list类型实际上就是一个指针。

    b)        va_start

    这个宏的作用是将T所指向的參数后面的内容放到ap中。当中_bnd (A,_AUPBND)是返回A的size并与系统的机器位数对齐。由于參数在栈中的地址一定是与系统的字长对齐的,当中acpi_native_int就表示机器字长。

    c)         va_end

    这个宏的作用就是返回0。

    d)        va_arg

    这个宏的作用是取得ap指向的当前的參数,并将ap指向參数列表中的下一个參数。 

  • 相关阅读:
    查看whl包名是否满足系统的条件的命令,以此解决whl包出现“is not a supported wheel on this platform”错误提示的问题
    C++-文件输入输出流
    C++-PTA-6-7-1 地下迷宫探索
    C++-PTA-时钟模拟
    数据结构-深入虎穴-树的应用
    数据结构-二叉树-(先序|后序)+中序求(后序|先序)笔记
    C++-课后习题-日期类DATE时间类Time
    C++-课后习题-学生类
    数据结构-串数组广义表笔记
    数据结构-PTA-银行业务队列简单模拟
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6932691.html
Copyright © 2011-2022 走看看