Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92401
  • 博文数量: 12
  • 博客积分: 1499
  • 博客等级: 上尉
  • 技术积分: 240
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-20 10:01
文章分类
文章存档

2010年(1)

2008年(11)

我的朋友

分类:

2008-09-16 15:31:46

lab1的头文件: inc/stdarg.h, 其全部内容如下:

#ifndef JOS_INC_STDARG_H
#define JOS_INC_STDARG_H

typedef char *va_list;

#define __va_size(type) \
        (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))

#define va_start(ap, last) \
        ((ap) = (va_list)&(last) + __va_size(last))

#define va_arg(ap, type) \
        (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))

#define va_end(ap)      ((void)0)

#endif  /* !JOS_INC_STDARG_H */


此文件用于函数调用时候对堆栈的处理。

宏 __va_size: 计算变量type的size。 由于在32-bit的机器上,堆栈的增减始终是以32bit为单位,所以必须将type处理成32-bit对齐。 引用项目中的一句原话:In 32-bit mode, the stack can only hold 32-bit values, and esp is always divisible by four. 该定义中使用long类型,说明所用的是32-bit机器。

宏 va_start(ap, last): 用于移动char*指针, 指向栈里last所在位置的下一个位置(即靠近栈底的位置)。 以函数cprintf()为例(kern/printf.c):
int
cprintf(const char *fmt, ...)
{
        va_list ap;
        int cnt;

        va_start(ap, fmt);
        cnt = vcprintf(fmt, ap);
        va_end(ap);

        return cnt;
}
则va_start(ap, fmt);之后,ap将指向fmt之后的参数。 假如有如下函数调用: cprintf("%s%d\n", "hello", 32); 则ap指向栈里保存字符串“hello“的位置。
之所以va_start将会向参数后面移动,从而指向栈的下一个位置,是因为函数调用时,入栈顺序是和参数位置相反的。因此,cprintf("%s%d\n", "hello", 32)的入栈位置为32, “hello“, ”%s%d\n", 而ap的值增加的结果就是向栈底移动,即va_start(ap, "%s%d\n")使ap从”%s%d\n"指向“hello“, 而va_start(ap, "hello")将使得ap从”hello“指向32。


宏 va_arg(ap, type): 返回栈里ap所指向的位置的值,并且将ap指向栈的下一个位置。假如有如下语句: cprintf("%s%d\n", "hello", 32); 其实现为: va_start(ap, "%s%d\n"), c=va_arg(ap, (char *)), 则此时ap指向32, c的值指向“hello“的指针。



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