Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519677
  • 博文数量: 96
  • 博客积分: 2102
  • 博客等级: 上尉
  • 技术积分: 1695
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:12
文章分类

全部博文(96)

文章存档

2014年(2)

2012年(94)

分类: C/C++

2012-04-21 10:03:40

       C语言有一个强大的功能,那就是它允许定义可接受一个可变参数列表的函数。
       为了访问一个可变参量,需要使用中的宏。他们允许在任何时候从头到尾便利一个附加参数列表,在遇到每个参数之前需要知道他的类型。
       对于获取输入、输出函数就是使用的变参列表。
     
  1. stdarg.h 文件:
  1. #ifndef _STDARG_H //为了防止该.h文件被多次包含。
  2. #define _STDARG_H

  3. typedef char * va_list;//将va_list 定义为char*类型

  4. #define __va_rounded_size(TYPE) \
  5.   (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

  6. #define va_start(AP, LASTARG) \
  7.  (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))

  8. void va_end (va_list);
  9. #define va_end(AP)
  10. #define va_arg(AP, TYPE) \
  11.          (AP += __va_rounded_size (TYPE)*((TYPE *) (AP - __va_rounded_size (TYPE))))
  12. #endif
解析:
  1.    __va_rounded_size(TYPE)  : 为了实现以4的倍数为基准的偏移,即TYPE = 2,通过宏之后结果为4
  2. va_start(AP, LASTARG) :获取第一个变参的地址。介绍一下,对于一个变参函数参数的组成(第一个固定参数,第一个可变参数,....第n个可变参数)是对ap的初始化
  3. va_arg(AP, TYPE) :遍历编参列表。使用的逗号表达式。从左开始执行,并且将最右侧的结果作为赋值结果。对于函数传递参数原则是:入栈操作,最后一个变参变量先入栈,然后根据从右到左的顺序依次入栈。
根据:C函数调用机制 了解到栈内部变量的分布情况:地址是从高到低(入栈的方向)。因此从栈底向上访问时
则需要将地址增加该变量的大小。
例子:
      
  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #define INTARG 1
  4. #define DBLARG 2

  5. void printargs(int *argtype, ...);
  6. int arg_types[]={INTARG,DBLARG,INTARG,DBLARG,0};

  7. void printargs( int*argtypep,...)
  8. {
  9.     int argtype;
  10.     va_list ap;
  11.    
  12.     printf("ap = %p\n",ap);
  13.     va_start(ap,argtypep);// ap=((char*)&(argtypep)+4);
  14.      printf("ap : %p *ap = %d \n", ap,(*(int *)ap));
  15.     while (( argtype = *argtypep++) != 0)
  16.     {
  17.         switch(argtype){
  18.             case INTARG:
  19.                  printf("ap :%p int :%d \n", ap,va_arg(ap,int));
  20.                  printf("argtypep : %p *ap = %d \n", &argtypep,(*(int *)ap));
  21.                  break;
  22.             case DBLARG:
  23.                 printf("ap: %p double: %f \n",ap, va_arg(ap, double));
  24.                  printf("arhtypep : %p *ap = %d \n", &argtypep,(*(int *)ap));
  25.                  break;
  26.                }
  27.     }
  28.     va_end(ap);
  29. }
  30.   int main()
  31.   {
  32.         printargs(&arg_types[0], 1, 2.0, 3, 4.0);
  33.         return 0;
  34.    }


    
阅读(1329) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~