免费注册 查看新帖 |

Chinaunix

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

可变参数的宏问题:va_start,va_arg,va_end [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-09-16 13:58 |只看该作者 |倒序浏览
Linux2.6.28的内核:
linux+v2.6.28/include/acpi/platform/acenv.h:

typedef char *va_list;
/*
275 * Storage alignment properties
276 */
277#define  _AUPBND                (sizeof (acpi_native_int) - 1)  //acpi_native_int 为32位(根据机子字数而定)
278#define  _ADNBND                (sizeof (acpi_native_int) - 1)  

/*
292 * Variable argument list macro definitions
293 */
294#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
295#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
296#define va_end(ap)              (void) 0
297#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

我的测试源代码如下:
#include <stdio.h>
#include <stdarg.h>
double sum_fun(int num, ...);
int main()
{
    double d;
    d = sum_fun(2, 5.5, 6.5);
    return 0;
}
double sum_fun(int num, ...)
{
    double sum = 0.0;
    double t;
    va_list argptr;
    va_start(argptr, num);
    for(; num; num--){
        t = va_arg(argptr, double);
        sum = sum + t;
    }
    va_end(argptr);
    return sum;
}
/********************************************************************************/
这里假设 &argptr = 0xbff69cd4,  &num = 0xbff69ce0。
首先解析va_start:
va_start(argptr, num);
argptr = (char *)&num + (sizeof(num) + 3) & ~(3) = 0xbff69ce0 + (0x00000007 & 0xFFFFFFF3) = oxbff69ce4
即 argptr 指向了下一个参数的地址

再来解析 va_arg:
t = va_arg(argptr, double);
*(double *)(  ((argptr) +=  (  (sizeof(double)  +  3)  &  ~(3))  )   -   ( (sizeof(double)  +  3)  &  ~(3)) ) )
= *(double *)(argpter + 8-8
这样的话等于没有改变argptr啊。它怎么可能指向下一个参数的地址呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP