近日在模式中进行非线性方程组求解时遇到变长参数函数的问题,以前从来没有自己写过变长参数的函数,于是补了一下课,将近日对该小问题的学习和理解整理如下。

一、变长参数函数(variadic function)[1,2]

其实我们在刚开始学习程序设计语言的时候就已经接触到变长参数函数,最明显的例子就是C中的printf函数,该函数的调用方式是printf(format,varibale_list),我们可以一次输出很多个变量,只要在format字符串中用%定义了这些变量的类型。再拿Wiki中的一段小程序[1]作为例子:

#include

double average(int count, ...)

{

va_list ap;

int j;

double tot =0;

va_start(ap, count);/* Requires the last fixed parameter (to get the address) */

for(j =0; j < count; j++)

tot +=va_arg(ap,double);/* Increments ap to the next argument. */

va_end(ap);

return tot / count;

}

这个函数的目的是求任意多个数的平均值,从这个例子中可以学习变长参数函数的使用方法:

1、采用#inculde 语句添加实现变参函数所需要的头文件

2、变长参数函数的声明和定义中用...表示变参列表

3、在函数内部用va_list关键字声明一个变参列表指针ap

4、用va_start将ap初始化为指向函数最后一个定参(在该例子中average函数的最后一个定参是count)处

5、用va_arg从变参列表中依次获取参数

6、用va_end将变参列表指针释放

那va_list类型以及va_start、va_arg、va_end到底是什么呢?答案是:宏。这些宏的定义位于stdarg.h(C)或者cstdarg.h(C++)中,包括上面提到的va_list类型以及va_start、va_end、va_arg和va_copy宏[3]。由于硬件平台和编译平台的不同[4],这些宏的定义和实现也有所差异。

二、GCC中的实现

在GCC的stdarg.h(/usr/lib/gcc/x86_64-redhat-linux/4.4.5/include)头文件中可以看到如下内容:

……

typedef __builtin_va_list __gnuc_va_list;

……

typedef __gnuc_va_list va_list;

……

#define va_start(v,l)   __builtin_va_start(v,l)

#define va_end(v)       __builtin_va_end(v)

#define va_arg(v,l)     __builtin_va_arg(v,l)

#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L || defined(__GXX_EXPERIMENTAL_CXX0X__)

#define va_copy(d,s)    __builtin_va_copy(d,s)

#endif

#define __va_copy(d,s)  __builtin_va_copy(d,s)

这说明gcc在这个头文件中定义了va_list类型和va_start、va_end、va_arg、和va_copy几个宏。关于这些宏的实现,在gcc中没有再找到其他信息,因为上面的定义中将va系列宏指向了_builtin_函数,这些函数编译器能自动识别并做相应处理[5]。

三、VC中的实现

在VC中这些宏的实现方式有明确定义: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 )

#define _INTSIZEOF(n)这句体现了programmer的智慧,需要详细分析才能理解,可参考[6]。额,注意到没,貌似VC不支持va_copy喔[7]。

References:转载本文请联系原作者获取授权,同时请注明本文来自彭彬科学网博客。

链接地址:http://blog.sciencenet.cn/blog-430991-700026.html

上一篇:让linux挂载的移动硬盘具有执行权限

下一篇:Fortran学习笔记(3): 一些非常有用的Fortran函数库

c语言 宏 变长参数,科学网—C/C++中处理变长参数函数(Variadic Function)的几个宏 - 彭彬的博文...相关推荐

  1. matlab surf颜色,科学网[转载]matlab中控制mesh或者surf的颜色

    科学网[转载]matlab中控制mesh或者surf的颜色 曲面的顏色越发柔順滑腻,del2 (Z) 根據數值微分來產生矩陣 Z 的 discrete Laplacian, Y,surf 及 mesh ...

  2. R语言ineq算基尼系数_科学网—一招搞定泰尔指数及其分解 - 王庆喜的博文

    一招搞定泰尔指数及其分解 上期讲了区位基尼系数,这期讲讲泰尔指数. 泰尔指数的原理同基尼系数,都是在测度一组数据分布的差异性.但是其有着良好的可分解性质,因此当需要考察产业空间集中度在不同区域层面的差 ...

  3. r语言 林元震_科学网—ASReml-R之简介 - 林元震的博文

    目前用于遗传分析的主要统计软件有SAS和SPSS等,并已经开发出了包括WOMBAT.MCMCglmm(R语言的程序包)等在内一系列遗传方差组份估计软件.ASReml是一个非常强大的统计软件,由NSW ...

  4. r语言 林元震_科学网—R语言简介 - 林元震的博文

    R既是软件,也是语言,在GNU协议General Public Licence下免费发行,是1995年由新西兰奥克兰大学统计系的Ross Ihaka和Robert Gentleman基于S语言基础上共 ...

  5. wannier拟合能带总是拟合不上_科学网—Wannier90输入文件中num_wann, num_bands, 和energy window等参数设置规则 - 李云海的博文...

    基本规则 Wannier90是一个构建局域轨道基组的有力工具,一般用来计算紧束缚模型中的占位能和跳跃积分,再结合杂化泛函或GW方法,插值得到更为准确的能带结构,或者计算极化.输运.拓扑不变量等物理性质 ...

  6. wannier拟合能带总是拟合不上_科学网-Wannier90输入文件中num_wann, num_bands, 和energy window等参数设置规则-李云海的博文...

    基本规则 Wannier90是一个构建局域轨道基组的有力工具,一般用来计算紧束缚模型中的占位能和跳跃积分,再结合杂化泛函或GW方法,插值得到更为准确的能带结构,或者计算极化.输运.拓扑不变量等物理性质 ...

  7. c语言补码链表重要吗,科学网—近期复习C语言的一些感悟 - 何亮的博文

    由于毕业论文基本顺利通过了盲审,工作也基本埃尘落定,离毕业还有些时间,正好利用这段空闲时间,好好学习一些技能.平时科研当中,用到计算机语言不少,但主要是一些脚本语言,如matlab,R等,也会用到一些 ...

  8. matlab绘制的图如何变得清晰科学网,科学网—[转载] MATLAB导出高清晰图片 - 刘若芸的博文...

    MATLAB导出高清晰图片 一个写论文用的小技巧,MATLAB产生的图片如何导出来合适大小或者符合编辑部要求的图片: 使用print命令,如下: 用于LaTeX的话,可以使用eps图片:print - ...

  9. matlab统计水文参数,科学网—[转载]利用MATLAB计算水文极值 - 刘朋的博文

    利用MATLAB计算水文极值(年最大值,年连续5日最大,连续干/湿日,连续极端径流低值日数) [filename,filepath]=uigetfile('*.*','请选择文件'); %计算水文极端 ...

最新文章

  1. Sublime Text 新建文件的模版插件: SublimeTmpl
  2. Windows下首次安装TensorFlow失败
  3. java sendmessage_SendMessage()复制/剪切/粘贴WM_COPYDATA 0x004A
  4. RTSP、RTMP和HTTP协议的区别
  5. P4070 [SDOI2016]生成魔咒
  6. Javassist实现JDK动态代理
  7. 随机森林降维matlab代码,随机森林代码实现问题
  8. ArcGIS API for Javascript之专题图的制作(四)热力图渲染(上)
  9. latex缩进与对齐_科学网—Latex算法排版,不同行缩进不同 - 张鹏的博文
  10. 2018年9月份计算机二级java无忧模拟软件破解版
  11. win10背景色改成豆沙绿,解决锁屏后失效方法
  12. 遇到unhandled exception:怎么处理?
  13. Uber无人车愈挫愈勇 估值百亿 已运送数万乘客
  14. 批处理系统脱机使用计算机,1.2.2 脱机输入/输出和批处理系统
  15. 【20180128】【matlab】均值、标准差、方差、协方差、中值的求解
  16. StringUtil工具类详解
  17. 调整Ubuntu16.04屏幕分辨率
  18. The Shawshank Redemption-6
  19. error LINK:1181 无法打开lib文件
  20. IntelliJ IDEA下载

热门文章

  1. UVa1422 - Processor(二分法)
  2. nginx的hash表结构
  3. HDU2094 产生冠军
  4. 机器学习——Java调用sklearn生成好的Logistic模型进行鸢尾花的预测
  5. java集合(List,Set,Map)详细总结
  6. php 超全局变量(整理)
  7. none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
  8. MHA高可用主从复制实现
  9. URL编码表%20Base64编码表%20HTTP消息含义
  10. d029: 求出2-100之间的所有质数(素数)