c语言va1是什么,c语言不定参数宏,va_start,va_arg的来历解释

本文详细介绍了_CINTSIZEOF宏的原理,以及va_start和va_arg两个宏的用途。va_start宏用于获取函数参数列表中第一个参数的地址,并转换为char*类型。va_arg宏则用于在参数列表中按类型前进并获取指定类型的参数值。通过这两个宏,可以处理可变参数列表,实现灵活的参数传递和读取。文章以实例解析了这两个宏的工作机制,展示了它们如何在函数参数存储于栈中的情况下工作。
摘要由CSDN通过智能技术生成

关于INTSIZEOF宏是怎么来的已经解释过了, 这里简要概述一下,宏定义如下:

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

当sizeof(n)<4时,宏的值就是4,当sizeof(n)>4时,宏的值就是4的倍数。

这里主要介绍两个宏va_start和va_arg两个宏,先说这个va_start。

宏定义如下:

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ),这里的va_list的类型是

char *,v是输入的第一个参数。首先在理解这个宏的前提要理解函数的形参是如何存储,这里我们做个试验如下图所示

形参是存储在栈里面的,栈的高地址在上,低地址在下,那么由上图可以得到的是,x,y,z在栈中存储的结构从上到下依次为z,y,x。那么(va_list)&v的意思就是取第一个参数的地址并强制转化为char*类型。比如这里的x的地址为1638116(十进制表示的)被强制转化为char*,对于_INTSIZEOF(v),若是这里的v也为x的话,那么这个宏的值为4。进而两者相加的值就是1638120。这里要说明的是地址的类型为char*的话,地址加1就相当于只是加1,比如这里的1638116 + 4 = 1638120;如果地址的类型是int *那么加1的意思就是地址+1*4。为什么???是这样的:比如一个指针指向一个int的输入比如int a[10],那么每一个元素就占4个字节所以地址+1中的1表示1*4,所谓的指针加几就是为了向前或者向后移动,那么移动多少字节就要取决于指针指向的变量的类型了,这样解释明白了吧!!!很基础是吧,比如数组是char型的,那么加1就是地址纯粹的加1了,因为sizeof(char) = 1的嘛。

好了,继续上面说的得到了地址1638116 + 4 = 1638120,那么这个1638120不正好就是y的地址值吗。所以这个宏的功能就是:输入第n个参数,输出的就是第n + 1个参数的地址值。再来介绍va_arg宏,它的定义如下:

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ),这里的t输入的是变量的类型,比如int,char等等之类的。ap += _INTSIZEOF(t)的意思让指针ap指向下一个参数的地址,在强调一遍高地址存的是函数越右边的形参值(因为形参是存在栈中的),比如假设ap指向的是x的地址,要使得ap指向y,那么由于x是在低地址那么就要加上x的类型,比如这里的x类型为int,所以这个时候ap是指向y的了。再减去_INTSIZEOF(t)(注意此时ap还是指向的y)那么((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))整个地址值就还原到原来的地方,也就是再次指向了x,为什么又要回来,其实就是为了使得ap指向下一个地址,然后再次回到原来的地址,在经过强制转化(t *),然后再取值*(t *)的符号“*”。

我们来捋一捋这个过程,假设函数只有x,y,z三个形参,一般先调用va_start使得ap指向了y,然后再调用va_arg,使得ap指向z,由于y的值没取出来进行计算,那么,就要把地址还原也就是上面再减去_INTSIZEOF(t),在取出y的值。那么这里就有一个问题是x的值并没用到,别急看完下面的例子就明白怎么用x的值了。

我们来举一个例子来应用一下,我们要实现,不管输入多少个参数,使得函数形参从第二个参数开始起进行累加,如下图所示:

a938af32071a41880312d8de2c029da1.png

function函数形参x表示的是有多少个参数,因为在执行va_start的时候就直接使得ap的指针指向了下一个形参的位置,所以可以利用x的值来表示有多少个参数,比如这里有4个参数,分别为0,1,2,3,4,那么function的功能就是把这几个值相加也就是6了。

举报/反馈

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值