C 函数中变化的参数用‘...’ 表示。变化的参数依旧按照C函数传参的规则入栈,即从右往左依次入栈,保证参数从左往右地址依次升高。

解析变参的主要思想是:将变参缓冲区像容纳了不同类型的数组(当然实际的数组里的变量类型不可能是不同的)一样对待。获取变参缓冲区首地址,按已知类型进行强转取值,跳过该值,取出下一个值,取完为止。

但是这里有涉及几个问题:

1,如何知道变参缓冲区的首地址?

2,强转时如何知道该参数的类型?

3,取出该值后,相应的游标应该偏移多少才能指向下一个参数首地址?

4,何时结束解析过程,即如何知道变参的个数?

下面依次解答上面的问题:

首先先看一段代码(摘自微软vadefs.h):

#elif   defined(_M_IX86)

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

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )
...
typedef char *  va_list;
#ifdef  __cplusplus
#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
#else
#define _ADDRESSOF(v)   ( &(v) )
#endif
... #define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end

首先应该明确栈中数据成员均按int型字节对齐。栈中的寻址均按int型字节进行。有了这个约定我们就能解决上面4个问题中最关键的两个问题1,3。

代码中 _INTSIZEOF(n) 计算出n所占字节是int字节数的倍数(向上取整)。

_crt_va_start(a,v) 给出变参缓冲区的首地址,等于与第一个变参左侧第一个形参的地址加上该形参字节对齐后应占的字节数。

_crt_va_arg(ap,t) 从宏可以看出t应该是一种类型。将ap所指地址强转成t * 然后取出该值,并将ap偏移到下一个参数首地址处。

相信看到这里,已经知道该怎么变参了。

至于如何知道参数个数,和参数类型,目前只能传参来解决,比如printf和scanf通过%来判断个数,通过%s,%d,%f等中s,d,f来区分类型。

C 中变参函数的处理方式的更多相关文章

  1. opengl es中不同的绘制方式

    opengl es中不同的绘制方式 转载请保留出处:http://xiaxveliang.blog.163.com/blog/static/297080342013467344263/ 1. GL_P ...

  2. 程序中保存状态的方式之Cookies

    程序中保存状态的方式之 Cookies,之前写过一篇关于ViewState的.现在继续总结Cookies方式的 新建的测试页面login <%@ Page Language="C#&q ...

  3. iOS中的数据持久化方式

    iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data. 1.属性列表 涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults ...

  4. VS中附加进程的方式调试IIS页面,以及设置断点无效问题解决

    以前调试网站的时候都习惯是直接在解决方案中右键调试——启动新实例,后来发现这样的缺点有: 1.启动比较慢: 2.一些浏览器的request参数无法带入: 3.不特殊指定启动url的话,VS会将页面加载 ...

  5. WCF中常用的binding方式

    WCF中常用的binding方式: BasicHttpBinding: 用于把 WCF 服务当作 ASMX Web 服务.用于兼容旧的Web ASMX 服务.WSHttpBinding: 比 Basi ...

  6. 程序中保存状态的方式之ViewState

    程序中保存状态的方式有以下几种: 1.Application 2.Cookie 3.Session 4.ViewState:ViewState是保存状态的方式之一,ViewState实际就是一个Hid ...

  7. Azure Service Bus 中的身份验证方式 Shared Access Signature

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  8. asp.net开发中常见公共捕获异常方式总结(附源码)

    本文实例总结了asp.net开发中常见公共捕获异常方式.分享给大家供大家参考,具体如下: 前言:在实际开发过程中,对于一个应用系统来说,应该有自己的一套成熟的异常处理框架,这样当异常发生时,也能得到统 ...

  9. 表单提交中get和post方式的区别

    表单提交中get和post方式的区别有5点 1.get是从服务器上获取数据,post是向服务器传送数据. 2.get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一 ...

随机推荐

  1. net core 实战之 redis 负载均衡和"高可用"实现

    net core 实战之 redis 负载均衡和"高可用"实现 1.概述 分布式系统缓存已经变得不可或缺,本文主要阐述如何实现redis主从复制集群的负载均衡,以及 redis的& ...

  2. ImportError: No module named _winreg

    在Flask项目部署到linux上时出现了一个问题,但是在windows上是好的,没有问题.以下是bug Traceback (most recent call last): File "f ...

  3. 快逸报表部署 (一)-- demo连接mysql数据库

    1. 设计器连接mysql数据库, 创建first.raq报表文件 2. 创建demo.jsp,嵌入报表,jsp顶部加入下面两行 <%@ page contentType="text/ ...

  4. How to Build Android Applications Based on FFmpeg by An Example

    This is a follow up post of the previous blog How to Build FFmpeg for Android.  You can read the pre ...

  5. 百分比布局实现响应式布局在 IE6 中填坑思路

    最近接了个政府项目,政府项目要求响应式,并且兼容IE6,不想用媒体监测的方法,于是用了百分比布局的方法,但是IE6真是名不虚传,做第一个界面就遇到了个bug ①两张宽度各占50%的图片无法在同一横排, ...

  6. 心情符号love

    写点什么呢,先谢谢心情吧,算是第一个脚印了,想先把之前的一些笔记和心得迁移进来吧,以后每个月都要充实自己的知识.向大婶们看齐.走你们走过的脚印,看你们前行的身影.沿着你们留下的路,继续为后者拓宽道路. ...

  7. zepto判断手机横竖屏

    var CheckOrientation = (function(){ var win = $( window ), get_orientation, last_orientation, initia ...

  8. JS 学习笔记--10---基本包装类型

    练习中使用的浏览器是IE10,如果有什么错误或者不同意见,希望各位朋友能够指正,练习代码附在后面 1.基本包装类型:    首先是基本类型,但又是特殊的引用类型,因为他们可以调用系统的方法,这种类型就 ...

  9. AngularJs学习笔记--Forms

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/forms 控件(input.select.textarea)是用户输入数据的一种方式.Form(表单) ...

  10. 零成本实现WEB性能测试(一)性能测试基础

    1.1 初识性能测试 概念:负载测试&压力测试. 目的:评估系统的能力,识别系统弱点,系统调优,检测问题,验证稳定性. 分类:负载测试,压力测试,容量测试 B/S指标: Avg Rps,平均每 ...