免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 980 | 回复: 3
打印 上一主题 下一主题

一个core问题,请高手指示 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-09-06 16:18 |只看该作者 |倒序浏览
#include<stdio.h>;
#include<string.h>;
#include<stdarg.h>;
int getVarArg(int a, int b, char * str, ...);
int fun2(va_list ap);
int main()
{
        getVarArg(1, 2, "tmpinfo", "first arg", "second arg", "third arg";
        return 0;
}

int getVarArg(int a, int b, char * str, ...)
{
        int ia = a;
        int ib = b;
        va_list ap;
        va_start(ap, str);
        fun2(ap);
        va_end(ap);
        return 0;
}
int fun2(va_list ap)
{
        char * t = NULL;
        t = va_arg(ap, char *);
        while(t != NULL)
        {
                printf("The var arg = %s\n", t);
                t = va_arg(ap, char *);
        }
        return 0;
}
运行结果:
The var arg = first arg
The var arg = second arg
The var arg = third arg
The var arg = 壜呉t?
The var arg = l?
The var arg = ZY?$
The var arg = ?縈
@珻@
The var arg =
The var arg = P瑗?

论坛徽章:
0
2 [报告]
发表于 2005-09-06 16:30 |只看该作者

一个core问题,请高手指示

getVarArg(1, 2, "tmpinfo", "first arg", "second arg", "third arg", NULL);

需要加一个NULL表示参数的结束.

论坛徽章:
0
3 [报告]
发表于 2005-09-06 16:30 |只看该作者

一个core问题,请高手指示

在stdarg.h头文件中,针对不同平台有不同的宏定义,我们选取X86平台下的宏定义:
typedef char *  va_list;
  #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

  #define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )

  #define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

  #define va_end(ap)      ( ap = (va_list)0 )
_INTSIZEOF(n)宏是为了考虑那些内存地址需要对齐的系统,从宏的名字来应该是跟sizeof(int)对齐。一般的sizeof(int)=4,也就是参数在内存中的地址都为4的倍数。比如,如果sizeof(n)在1-4之间,那么_INTSIZEOF(n)=4;如果sizeof(n)在5-8之间,那么_INTSIZEOF(n)=8。

  为了能从固定参数依次得到每个可变参数,va_start,va_arg充分利用下面两点:

  1. C语言在函数调用时,先将最后一个参数压入栈

  2. X86平台下的内存分配顺序是从高地址内存到低地址内存

  高位地址

  第N个可变参数

  。。。

  第二个可变参数

  第一个可变参数      ? ap

  固定参数           ? v

  低位地址

  由上图可见,v是固定参数在内存中的地址,在调用va_start后,ap指向第一个可变参数。这个宏的作用就是在v的内存地址上增加v所占的内存大小,这样就得到了第一个可变参数的地址。

  接下来,可以这样设想,如果我能确定这个可变参数的类型,那么我就知道了它占用了多少内存,依葫芦画瓢,我就能得到下一个可变参数的地址。

  让我再来看看va_arg,它先ap指向下一个可变参数,然后减去当前可变参数的大小即得到当前可变参数的内存地址,再做个类型转换,返回它的值。

  要确定每个可变参数的类型,有两种做法,要么都是默认的类型,要么就在固定参数中包含足够的信息让程序可以确定每个可变参数的类型。比如,printf,程序通过分析format字符串就可以确定每个可变参数大类型。

  最后一个宏就简单了,va_end使得ap不再指向有效的内存地址。

其实在varargs.h头文件中定义了UNIX System V实行的va系列宏,而上面在stdarg.h头文件中定义的是ANSI C形式的宏,这两种宏是不兼容的,一般说来,我们应该使用ANSI C形式的va宏。

论坛徽章:
0
4 [报告]
发表于 2005-09-06 16:42 |只看该作者

一个core问题,请高手指示

果然都是高手,我爱这个论坛,谢谢:)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP