免费注册 查看新帖 |

Chinaunix

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

请教c可变参数中宏定义实现的问题 (#define va_arg(ap,t) ****) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-10-09 17:51 |只看该作者 |倒序浏览
小弟初次研究可变参数的问题,下午在看其中的几个宏定义。
有些疑惑,望各位大侠指教。

系统中宏定义如下:
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 )


解释如下:
看va_start的定义,定义为&v+_INTSIZEOF(v),而&v是固定参数在堆栈的
地址,所以我们运行va_start(ap, v)以后,ap指向第一个可变参数在堆
栈的地址

首先ap+=sizeof(int),已经指向下一个参数的地址了.然后返回
ap-sizeof(int)的int*指针,这正是第一个可变参数在堆栈里的地址
(图2).然后用*取得这个地址的内容(参数值)


这样我有一个很疑惑的地方,在定义宏va_start(ap,v)的时候,ap已经指向了第一个可变参数的地址,为什么还要先加 _INTSIZEOF(t),然后再减去 _INTSIZEOF(t)这样的操作,用来获得第一个可变参数的地址呢?
不是多此一举吗?
不过既然这样做了,一定有可取的地方。望各位大侠指教小弟!!!!!

论坛徽章:
0
2 [报告]
发表于 2005-10-09 20:47 |只看该作者

请教c可变参数中宏定义实现的问题 (#define va_arg(ap,t) ****)

原帖由 "ramon_818" 发表:

这样我有一个很疑惑的地方,在定义宏va_start(ap,v)的时候,ap已经指向了第一个可变参数的地址,为什么还要先加 _INTSIZEOF(t),然后再减去 _INTSIZEOF(t)这样的操作,用来获得第一个可变参数的地址呢?
不是多此一举吗?


之所以要“多此一举”就是为了在一个宏体之内做完所有要做的事情。

举个例子,当你用一个指针操作一个链表的时候,除了处理当前节点之外,
是不是还要把指针移向下一个节点呢?这里的ap+=....就是做这个事情的。
用括号括起来的+=操作本身与“当前节点”无关,是为“下一个节点”做
准备的,和当前节点有关的仅仅是整个+=表达式的值。。。

没时间细看,随便说了两句,不知道是不是这个意思?

论坛徽章:
0
3 [报告]
发表于 2005-10-10 01:41 |只看该作者

请教c可变参数中宏定义实现的问题 (#define va_arg(ap,t) ****)

原帖由 "雨丝风片" 发表:


之所以要“多此一举”就是为了在一个宏体之内做完所有要做的事情。

举个例子,当你用一个指针操作一个链表的时候,除了处理当前节点之外,
是不是还要把指针移向下一个节点呢?这里的ap+=....就是做这个事情?.........


楼上说到了点子上,补充一点;
可以把va_arg(ap,t)认为是一个函数;
功能是 整个返回值 指向具体参数,t可认为是该参数的数据类型,ap指向该参数的下一参数在栈中的位置。
变参的思路就是:第1个参数知道类型和地址后,第2个参数就可在只知道类型的情况下知道它在栈中的位置,以此类推。

论坛徽章:
0
4 [报告]
发表于 2005-10-10 13:23 |只看该作者

请教c可变参数中宏定义实现的问题 (#define va_arg(ap,t) ****)

谢谢楼上两位大侠教诲。领教了!多谢多谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP