8_7 C语言 | 探寻可变参数列表

本文深入剖析了可变参数列表的实现原理,并通过一个具体的代码示例解释了va_list、va_start、va_arg和va_end宏的具体作用及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可变参数列表剖析

附上一段代码

#include <stdarg.h>
int aver(int n,...)
{
    int i = 0;
    int sum = 0;
    va_list arg;
    va_start(arg, n);
    for(i = 0; i<n; i++)
    {
        sum += va_arg(arg,int);
    }
    va_end(arg);
    return sum/n;
    }
#

typedef char * va_list;
我们发现va_list实际上是char * ,因此上一段代码 arg被定义成一个字符串指针;

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

_INTSIZEOF(n) 是一个宏,是向上求整,大小为4的倍数,如图所示:
这里写图片描述
va_start实际上也是一个宏,上段代码的va_start(arg, n);可根据替换为
(arg = (char *)&n + 4)

#define va_arg(ap,t) ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
va_arg(ap,t) 也是一个宏,上段代码va_arg(arg,int)替换后为((int )((arg += 4) - 4))。我们发现,arg已经指向了下一个整形值,而整个表达式还指向原表达式,类似于自加的效果;

#define va_end(ap) ( ap = (va_list)0 )
上段代码:va_end(arg) 是将 arg指向0;

因此上段代码可改为如下:
int aver(int n,...)
{
    int i = 0;
    int sum = 0;
    char *arg;
    va_start(arg, n);
    arg = (char *)&n + 4;
    for(i = 0; i<n; i++)
    {
        sum += (*(int *)((arg += 4) - 4));
    }
    arg = (char *)0;
    return sum/n;
}

注释了的代码:

#include <stdarg.h>
int aver(int n,...)
{
    int i = 0;
    int sum = 0;
    va_list arg; //char *arg;
    va_start(arg, n);
    //(arg = (char *)&n + _INTSIZEOF(n));//_INTSIZEOF是向上取整;
    //(arg = (char *)&n + 4);//指向[参数总个数]后的第一个参数;
    for(i = 0; i<n; i++)
    //va_start:初始化arg,让其指向未知参数后的第一个参数;
    {
        sum += va_arg(arg,int);//int 不能写错
        //sum += (*(int *)((arg += 4) - 4));
    }
    va_end(arg);//arg = (char *)0;
    return sum/n;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BugGuys

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值