设为首页 加入收藏

TOP

C语言可变长参数实现原理
2015-01-22 21:37:38 来源: 作者: 【 】 浏览:79
Tags:语言 可变 参数 实现 原理
?

(1) C语言可变参数

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

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

下面一个函数myprintf是自己实现的比较简单的printf函数,不完整但是可以说明可变参数的用法。
/*
 * Author: guojun07
 */

#include 
  
   
#include 
   
     #include 
    
      #include 
     
       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指向参数列表中的下一个参数;

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中static的使用 下一篇C程序堆、栈存取效率对比

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: