免费注册 查看新帖 |

Chinaunix

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

va_list这样的东东究竟是怎么回事? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-09-13 17:32 |只看该作者 |倒序浏览
下面是vc里面的源代码。不过到了第二行我就看不懂意图了

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 )

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2004-09-13 20:59 |只看该作者

va_list这样的东东究竟是怎么回事?

var_list就是个char *

论坛徽章:
0
3 [报告]
发表于 2004-09-13 22:14 |只看该作者

va_list这样的东东究竟是怎么回事?

这个我也知道,问题是继续看下去就看不懂它的工作原理了
不知道这段短短的代码是如何利用ap和t来将可变个数个参数整合到一个自字符串里去的

论坛徽章:
0
4 [报告]
发表于 2004-10-18 16:15 |只看该作者

va_list这样的东东究竟是怎么回事?

va_list 好象是C的一个类型,这个数据类型可以用来指向一个实参数组--用于可变个数参数。具体细节我也不清楚了,请高手解释一下。

论坛徽章:
0
5 [报告]
发表于 2004-10-18 17:24 |只看该作者

va_list这样的东东究竟是怎么回事?

原来va_list就是char *啊,嘿嘿现在看看,原来是这样,以下为个人看法,
如果对了,纯属巧合
==================================
假设写了一个变参数个数的函数如下
void test(char *fmt, ...)
{
        va_list myVa;
        va_start(myVa, fmt);
        ....
}

根据楼主提供的宏扩展以后
myVa = ((char*)&fmt + (sizeof(fmt)+sizeof(int)-1)&~(sizeof(int)-1)

sizeof(int) = 2; //16机器, 0x0010                                        sizeof(int)-1=0x0001
sizeof(int) = 4; //32机器, 0x0000 0100                       
                                sizeof(int)-1=0x0000 0011
sizeof(int) = 8; //64机器, 0x0000 0000 0000 1000       
                                sizeof(int)-1=0x0000 0000 0000 0111

思路:
变参数的函数, 用va_start来获得第一个变参的地址
fmt为函数调用中上一个参数在栈中的地址,
sizeof(fmt)为该参数的实际大小,
本来fmt的地址+fmt大小(也就是地址偏移应该已经可以获得下一个参数的地址了)
为什么还有sizeof(int)呢, 考虑函数调用可能有类似字节对齐的要求,
那么sizeof(int)在16,32,64位机器上分别为2,4,8

所以对sizeof(fmt)有两种情况, 一是已经符合要求, 刚好对齐
一是不符合要求, 不对齐, 那么根据要求是要多算上1,3,7个字节的
那么sizeof(fmt)+sizeof(int)-1
对第一种情况, 多加了几个字节, 是需要去掉的
对第二种情况, 加上后可能刚好满足要求, 也可能又多出了几个字节

对这两种情况都有多出的字节, 但很明显多出的字节小于1,3,7
所以看看& ~(sizeof(int)-1) 明白了吧, 把末尾几位都给去掉了

对2来说0~1是没有意义的
对4来说0~3是没有意义的
对8来说0~7是没有意义的
所以分别将sizeof(int)-1取反后再&, 将末尾的去掉

那么就大功告成了,也就是说是根据上一个参数的地址和大小取到下一个参数的地址

论坛徽章:
0
6 [报告]
发表于 2004-10-18 17:27 |只看该作者

va_list这样的东东究竟是怎么回事?

va_arg没再想过,偶已经很满足了,留给别人思考吧,

论坛徽章:
0
7 [报告]
发表于 2004-10-18 17:57 |只看该作者

va_list这样的东东究竟是怎么回事?

查查man帮助,一段模拟printf的代码:
#include <stdio.h>;
#include <string.h>;
#include <stdlib.h>;
#include <stdarg.h>;

void foo(char *fmt,...)
{
        va_list ap;
        int d;
        char c,*s;
        int i=0;
        va_start(ap,fmt);
        while(i<strlen(fmt))
        {
        if (fmt=='%')       
        {
                switch(fmt[++i])
                {
                        case 's':
                                s=va_arg(ap,char*);
                                printf("%s",s);
                                i++;
                                continue;
                        case 'd':
                                d=va_arg(ap,int);
                                printf("%d",d);
                                i++;
                                continue;

                        case 'c':
                                c=(char)va_arg(ap,int);
                                printf("%c",c);
                                i++;
                                continue;
                        default:
                                printf("%%";
                                continue;
                }
               
        }
        else
        {
                printf("%c",fmt);
                i++;
        }
        }
        va_end(ap);
       
}

论坛徽章:
0
8 [报告]
发表于 2004-10-18 18:02 |只看该作者

va_list这样的东东究竟是怎么回事?

不知道楼上是来干什么的,有没有看清别人在问什么...

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
9 [报告]
发表于 2004-10-18 18:08 |只看该作者

va_list这样的东东究竟是怎么回事?

http://bbs.chinaunix.net/forum/viewtopic.php?t=423149&highlight=aero

大家也去看看这个链接,可以回答楼主的问题,另外,还有其他的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP