可变参数列表

可变参数列表的使用是很有必要的一件事情,在实现某个功能时,你可能不知道传几个参数。下面简单介绍一下可变参数列表的使用。

可变参数列表是通过宏来实现的,定义与stdarg.h头文件中。

void va_start(va_list ap, last); //va_start用来初始化参数列表t
type va_arg(va_list ap, type); //va_arg用来获取参数列表中的一个参数,类型为type。
void va_end(va_list ap); //va_end用来清理参数列表。
void va_copy(va_list dest, va_list src); //va_copy用来拷贝参数列表

下面是这些函数宏的实现

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_list

typedef char * va_list; 
/*宏的定义
把char*重命名为va_list,使得va_list定义的指针变量可以访问到未知参数列表*/

va_start

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
/*初始化参数列表
 _INTSIZEOF(v)的作用是跳过最后一个已知变量v,ap取到未知参数列表的第一个参数,完成参数列表的初始化*/

va_arg

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
/*取出当前参数
t是未知参数列表中参数的类型。
((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))的作用是使得每次调用va_arg都能使指针自动往后移动一位,本次对本参数访问的同时,下次可以访问到下一个参数。/

va_end

#define va_end(ap) ( ap = (va_list)0 )
/*清空参数列表
把指向参数列表的指针置为0,达到清理参数列表的目的*/

接下来具体介绍可变参数列表的使用

1.求n 个数的平均数

#include<stdarg.h>
#include<stdio.h>

int Average(int n,...)
{
    int i = 0;
    int sum = 0;
    va_list arg; 
    //char* arg 类型重命名

    va_start(arg, n);
    // #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) 宏的实现
    // 替换后  ( arg = (char*)&n + 4 )
    for (i = 0; i < n; i++)
    {
        sum += va_arg(arg, int);
        //#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) 宏的实现
        //替换后 sum += ( *(int*)((arg += 4) - 4)) 
    }
    va_end(arg);
    //#define va_end(ap) ( ap = (va_list)0 )
    //替换后 (arg = (char*)0 );
    return sum / n;
}

int main()
{
    int ave = Average(3, 1, 2, 3);
    printf("ave = %d\n", ave);
    system("pause");
    return 0;
}

2.求取参数部分n个里面的最大值

#include<stdarg.h>
#include<stdio.h>

int Max(int n, ...)
{
    int i = 0;
    va_list arg;
    va_start(arg, n);
    int tmp = va_arg(arg, int); //tmp 用来保存第一个数 即-3
    for (i = 0; i < n-1; i++)
    {
        int tmp1 = va_arg(arg, int); // 此时 tmp1 用来保存后面的数 ,即循环一次访问一个接下来元素
        if (tmp < tmp1)
        {
            tmp = tmp1;
        }
    }
    return tmp;
}

int main()
{
    int max = Max(3, -3, -1, -2);
    printf("max = %d\n", max);
    system("pause");
    return 0;
}

3.printf函数的模拟实现

#include<stdarg.h>
#include<stdio.h>
#include<assert.h>
void display(int n)
{
    if (n > 9)
    {
        display(n / 10);
    }
    putchar(n % 10 + '0');

}
void print(char *format, ...)
{
    assert(format != NULL);
    va_list arg;
    va_start(arg, format);
    while (*format)
    {
        switch (*format)
        {
            case 's':
            {
                    char *ret = va_arg(arg, char*);
                    while (*ret)
                    {
                        putchar(*ret);
                        ret++;
                    }
            }
                break;
            case 'c':
            {
                    char ret = va_arg(arg, char);
                    putchar(ret);
            }
                break;
            case 'd':
                display(va_arg(arg, int));
                break;
            default:
                putchar(*format);
                break;
        }
        format++;
    }
}
int main()
{
    print("s ccc d.\n", "hello", 'B', 'A', 'T', 100);
    system("pause");
    return 0;
}

以上就是我对可变参数列表的一些理解,有不对的地方还希望指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值