首页 技术 正文
技术 2022年11月23日
0 收藏 316 点赞 2,462 浏览 941 个字

  这几个函数和变量是针对可变参数函数的,什么是可变参数函数呢,最经典的莫过于printf和scanf,这两个函数的声明如下:

 int printf(const char *format, ...); int scanf(const char *format, ...);

  这两个函数声明中省略号(…)表示的就是任意个数的参数,可变参数函数就是输入的参数的个数是可变的,那么这个具体是怎么实现的呢?

  要了解这个是怎么实现,首先我们就要先理解一点,参数是如何传递给函数的。众所周知,函数的数据是存放于栈中的,那么给一个函数传递传递参数的过程就是将函数的参数从右向左逐次压栈,例如:

  func(int i, char c, doube d)

  这个函数传递参数的过程就是将d,c,i逐次压到函数的栈中,由于栈是从高地址向低地址扩展的,所以d的地址最高,i的地址最低。

  理解了函数传递参数的过程,再来说一下va_list的原理,通常,可变参数的代码是这么写的:

 void func(char *fmt, ...)
{
va_list ap; va_start(ap, fmt);
va_arg(ap, int);
va_end(va);
}

  这里ap其实就是一个指针,指向了参数的地址。

  va_start()所做的就是让ap指向函数的最后一个确定的参数(声明程序中是fmt)的下一个参数的地址。

  va_arg()所做的就是根据ap指向的地址,和第二个参数所确定的类型,将这个参数的中的数据提取出来,作为返回值,同时让ap指向下一个参数。

  va_end()所做的就是让ap这个指针指向0。

  关于这三个参数实现的宏可以参看下面的实现:

 // 使ap指向第一个可变参数的地址
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) // 使ap指向下一个可变参数,同时将目前ap所指向的参数提取出来并返回
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) // 销毁ap
#define va_end(ap) ( ap = (va_list)0 )

参考文章:

1. 详解 C语言可变参数 va_list和_vsnprintf及printf实现

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848