正在加载...

C 可变长参数

[ 2011/09/02 21:03 | by selboo ]

      其实我们接触的第一个C语言函数 int printf(const char *format, ...);就是可变长参数实现的。open函数就有两个原型 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
但是这并不是函数重载,因为C语言是不支持函数重载的。这是利用变长参数实现的。
This is The C Code
[root@selboo.com.cn ~]$ cat c.c
#include <stdio.h>
int main ()
{
        int a = 1, b = 2;
        printf ("Selboo...\n");
}
[root@selboo.com.cn ~]$ gcc c.c
[root@selboo.com.cn ~]$ ./a.out
Selboo...
Parsed in 0.004 seconds at 44.62 KB/s

上面 printf 就是可变长参数,它的原型声明 在 stdio.h 里面可以找到.
This is The C Code
[root@selboo.com.cn ~]$ cat c.c
int printf(const char *format, ...);

int main ()
{
        int a = 1, b = 2;
        printf ("Selboo... a=%d,b=%d\n",a, b);
}
[root@selboo.com.cn ~]$ gcc c.c
[root@selboo.com.cn ~]$ ./a.out
Selboo... a=1,b=2
Parsed in 0.004 seconds at 53.65 KB/s

int printf(const char *format, ...);  用三个点 "..." 做参数占位符
        
      在stdarg.h这个头文件中,C语言给我们提供了实现变长参数的便利:一个类型 va_list, 三个宏 va_start , va_arg , va_end。下面给出一个简单的例子,大家就能比较明白了
This is The C Code
[root@selboo.com.cn ~]$ cat b.c
#include <stdio.h>
#include <stdarg.h>

int sum(int n,...)  //必须给定一个固定的参数
{
        int i;
        int sum=0;
        va_list ap;   //定义一个变量 ,保存函数参数列表的指针
        va_start(ap,n);  // 用va_start宏初始化变量ap,va_start宏的第2个参数就是我们自定义的固定参数
        for(i=0;i<n;i++){
                sum+=va_arg(ap,int);   //va_arg取出当前的参数,使用对应类型的变量接收
        }
        va_end(ap);
}
int main()
{
        printf("sum=%d",sum(4,1,2,3,4));  //固定参数在这里指定要参加运算的参数个数
        printf("sum=%d",sum(10,1,2,3,4,5,6,7,8,9,10));
}
Parsed in 0.007 seconds at 95.09 KB/s

其实va_arg这个宏的最基本原理就是,函数的参数是按照从右至左逐个入栈的,栈的延伸方向是从高地址到低地址,栈底的占领着最高内存地址,先入栈的参数,其地理位置也就高了。
例如函数sum(a,b),va_arg实现类似于 b.addr = a.addr + x_sizeof(a)的功能,只是x_sizeof(a)在这里并不是简单的sizeof(),因为编译器在栈上压入参数时,并不是一个紧挨着另一个的。这样编译器就能逐个调用参数了。
最后编辑: selboo 编辑于2011/11/06 01:14
Tags: , ,
,
发表评论
表情
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]