可变参数列表解析

可变参数

在写c程序时,我们经常使用到printf这个函数,那么在使用这个函数时,我们给他传参吗?传几个参数?
可以看一下函数原型:
这里写图片描述
可以看出,printf也是有参数的,并且可以传1个以上任意多个参数。
这就是可变参数。
举一个实例来说明:

int average(int n, ...)
{
    va_list arg;//定义一个指针变量
    int i = 0;
    int sum = 0;
    va_start(arg, n);//指向可变参数列表部分
    for (i = 0; i<n; i++)
    {
        sum += va_arg(arg, int);//读取每一个参数,并且加到一起
    }
    return sum / n;
    va_end(arg);//结束读取
}
int main()
{

    int a = 1;
    int b = 2;
    int c = 3;
    int avg = average(3, a, b, c);
    printf("avg = %d\n", avg);

    system("pause");
    return 0;
}

这里写图片描述

对于关键宏的解读

此处使用的宏都在stdarg.h头文件中包含。
1.va_list
宏:#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
实现:实际上只是一个 char * 类型的指针。

2.va_start
宏:#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
这个宏需要两个参数,第一个是上面定义的 va_list, 第二个是可变参数列表之前的那个参数。
注意:va_start中的参数,一定要是已知的最后一个参数,即就是…之前的那个参数。

3.va_arg
宏:#define va_arg(ap,t) ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
同样有两个参数,第一个是前面已经初始化好的 va_list,第二个是类型,比如这里可变参数列表的第一个参数是int类型,那么就传int。

4.va_end
宏:#define va_end(ap) ( ap = (va_list)0 )
为了更好的可读性,结束可变参数的获取。

可变参数的限制

注意

  • 可变参数必须从头到尾访问。可以在访问几个可变参数之后终止,但不能从一开始就访问参数列表中间的参数。
  • 参数列表中至少要有一个已知的命名参数,不能一个都没有,否则无法使用va_start。
  • 这些宏是无法直接判断实际存在参数的数量。
  • 并且宏也无法判断每个参数的类型。

实现printf函数

再了解了可变参数列表之后,可以实现一个我们自己的printf函数。

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
void print(char *format,...)
{
    va_list(arg);
    va_start(arg, format);
    while (*format)
    {

        switch (*format)
        {
        case 's':
            {
                    char *str = va_arg(arg, char*);
                    while (*str)
                    {
                        putchar(*str);
                        str++;
                    }
            }
            break;
        case 'c':
            {
                    char c = va_arg(arg, char);
                    putchar(c);
            }
            break;
        default:
            break;

        }
        format++;
    }
    va_end(arg);
}
int main()
{
    print("s cccccc d.\n","hello",'\t','w','o','r','l','d',100)

    system("pause");
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值