c语言实现函数的可变参数

作者: dreamfly 分类: 个人博客 发布时间: 2019-03-30 10:26

有时候,我们希望我们的函数的参数是动态变化的。例如:

int func(int,..)

int func(2,1,2)

int func(3,2,2,9)

我们可以通过制定参数的个数,来动态添加参数。那么c语言是如何实现这个功能的呢?c语言提供了标准函数库,我们只需要引入stdarg.h这个头文件就可以了。

下面介绍如何正确使用这个功能。

  • 定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。

  • 在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。

  • 使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。

  • 使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。

  • 使用宏 va_end 来清理赋予 va_list 变量的内存。

  

具体代码如下:

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

double average(int num,...){
va_list valist;
double sum = 0.0;
int i;
/* 为 num 个参数初始化 valist */
va_start(valist, num);
/* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* 清理为 valist 保留的内存 */
va_end(valist);
return sum/num;
}
int main(){
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

其实我们如果深入研究就会发现,valist其实是个指针,它通过不断指向后面的可变参数来获取参数的值,它是通过第一个参数来确定循环的次数的,也就是说,上面我们的函数第一个参数如果为3,后面的参数即使有100个,它也只会取前面3个的平均值。

我们看下va底层是如何定义实现的。

#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_arg这个函数,我们就可以获取下一个参数的地址,因为参数的类型不确定,所以我们用sizeof(t)来获取占用位置大小。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

10条评论
  • Waypoxy

    2021年7月1日 06:45

  • ValfKeeli

    2022年7月27日 02:16

    Progesterone Gestagen cialis 5 mg Viagra 100mg Cost

  • Obedoms

    2022年8月15日 06:55

    Prix Du Viagra Pharmacie En Le Tampon buy stromectol for dogs

  • Haintailk

    2022年9月2日 08:18

    Safe and regulated treatments 100 discreet and confidential U cialis and viagra sales our erectile dysfunction treatment Levitra Fx adj

  • optonse

    2022年9月4日 13:54

    Adaptation Stop Start Technique Squeeze Technique Quiet Vagina Applying local anesthetic A variety of prescription medications priligy precio Tadalafil 40mg Dapoxetine 60mg Tablets medication should be consumed only with the help of water, this medication should be used at least 30-45 minutes before lovemaking and the effects of this medicine can be experienced for a long period of time that is for almost 36 hours

  • Issueks

    2022年9月6日 12:27

    Sildenafil and Tadalafil have been around since 2017 and both erectile dysfunction treatments have their ups and downs, along with different outcomes for different people; everyone s body is different buy cialis online canadian pharmacy Clin Pharmacokin

  • absotatot

    2022年9月8日 20:33

    Submitted by Nlbxsaumn From Yako purchasing cialis online He feels like a man again, his penis is hard with a big head so he can be proud

  • autolla

    2022年9月11日 11:27

    Like this morning all of a sudden right after I after I suddenly felt so queasy that I grabbed my mouth and stomach and then quickly let it go as something else. most reliable site to buy clomid

  • mumClulky

    2022年9月14日 15:37

    Ttc20178 BFP. nolvadex pct for sarms

  • idionmelm

    2022年9月18日 06:14

    Doxycycline Lindox- L Capsule and Doxycycline Lindox- L Capsule CAP are indicated for the prophylaxis of malaria due to Plasmodium falciparum in short- term travelers less than 4 months to areas with chloroquine and or pyrimethamine- sulfadoxine resistant strains. how long does sun sensitivity last after doxycycline

发表评论

您的电子邮箱地址不会被公开。