1. 在C中,当无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表。例如:

void foo(...);
void foo(parm_list,...);

2. 函数参数的传递原理

函数参数是以栈的形式存取,从右至左入栈。

参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:

void func(int x, float y, char z);

那么,调用函数的时候,实参 char z 先进栈,然后是 float y,最后是 int x,因此在内存中变量的存放次序是 x->y->z。从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。举个例子如下:

#include <stdio.h> //获取参数列表中的所有参数,并打印
void PrintInt(int cnt, ...)
{ int *temp = &cnt;temp++;for (int i = 0; i < cnt; ++i) { printf("%d\n", *temp); temp++; }
}int main(void)
{int a = 1; int b = 2; int c = 3; int d = 4;PrintInt(4, a, b, c, d); return 0;
}

执行程序后输出:




4

3. 利用Va_start相关宏获取省略号指定的参数

下面是 <stdarg.h> 里面重要的几个宏定义如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap ); 

说明:

1)va_list:一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。

2)va_start:对ap进行初始化,让ap指向可变参数表里面的第一个参数。第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即“...”之前的那个参数;

3)va_arg: 获取参数。它的第一个参数是ap,第二个参数是要获取的参数的指定类型。按照指定类型获取当前参数,返回这个指定类型的值,然后把 ap 的位置指向变参表中下一个变量的位置;

4)va_end:释放指针,将输入的参数 ap 置为 NULL。通常va_start和va_end是成对出现。

使用上面的宏获取参数的步骤如下:

<Step 1> 定义一个 va_list 类型的变量,(假设va_list 类型变量被定义为ap);
    <Step 2> 调用va_start ,对ap 进行初始化,让它指向可变参数表里面的第一个参数。

<Step 3> 获取参数,并使用参数。
<Step 4> 获取所有的参数之后,将 ap 指针关掉。
给出一个例子如下:
#include 〈stdio.h〉
#include 〈string.h〉
#include 〈stdarg.h〉
/*ANSI标准形式的声明方式,括号内的省略号表示可选参数*/
int demo( char msg, ... )
{ /*定义保存函数参数的结构*/va_list argp; int argno = 0; char *para; /*argp指向传入的第一个可选参数,msg是最后一个确定的参数*/ va_start( argp, msg ); while (1) { para = va_arg( argp, char*); if ( strcmp( para, "") == 0 ) break; printf("Parameter #%d is: %s\n", argno, para); argno++;
}
va_end( argp );
/*将argp置为NULL*/
return 0;
}
void main( void )
{ demo("DEMO", "This", "is", "a", "demo!", "");
} 

va_start和va_end详解相关推荐

  1. [C语言] va_start和va_end详解

    在C中,当无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表.例如: void foo(...); void foo(parm_list,...); 函数参数的传递原理 函数参数是以栈的 ...

  2. va_start和va_end使用详解

    va_start和va_end使用详解 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个 ...

  3. 不确定函数参数个数时的处理,va_start和va_end使用详解

    引出   在C中,当我们无法确定函数的所有实参的类型和数目时,可以用省略号指定参数表来处理,如: void foo(...); void foo(parm_list,...);   具体怎么使用呢,我 ...

  4. java va start_va_start和va_end使用详解

    本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解. 介绍这两 ...

  5. Win32开发之Format MessageBox 详解

    本文介绍在Windows程序开发中的MessageBox详解.   我们在在Windows程序设计中经常会涉及到一个格式化消息框,其代码如下: #include <windows.h> # ...

  6. linux 进程间通信 dbus-glib【实例】详解四(上) C库 dbus-glib 使用(附代码)(编写接口描述文件.xml,dbus-binding-tool工具生成绑定文件)(列集散集函数)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  7. C 和 C++ 宏 详解

    From:https://www.cnblogs.com/njczy2010/p/5773061.html C中的预编译宏详解:http://www.cppblog.com/bellgrade/arc ...

  8. 【C++】Web服务器项目所用到的函数详解

    文章目录 1 Web服务器端监听 1.1 socket()函数 1.2 struct sockaddr和struct sockaddr_in结构体(INADDR_ANY) 1.3 bzero()函数 ...

  9. imx6ul 驱动详解

    链表的知识: struct list_head {struct list_head *next, *prev; }; API函数 函数 功能 LIST_HEAD 声明并初始化双向链表. INIT_LI ...

最新文章

  1. Swift3.0语言教程删除字符与处理字符编码
  2. keepalived实现Tomcat服务双机热备
  3. MS UC 2013-0-虚拟机-标准化-部署-1-虚拟化-部署
  4. 1.2)深度学习笔记------神经网络的编程基础
  5. linux系统如何拨号上网连接,教你在Linux下如何使用ADSL拨号上网
  6. 用Python增强Excel的3大集成方法及用途
  7. 深入理解 OUI(Oracle Universal Installer)
  8. CodeIgniter的缓存小记
  9. mysql中数据导出到json文件的读取办法:
  10. css在线代码生成工具汇总
  11. gaussdb 日常运维命令总结【01】
  12. SVN Working copying #39;xxxxx/xxxx/xxxx#39; locked
  13. ubuntu中如何修改计算机名字
  14. 避雷器的测试项目及方法
  15. 微信公众平台找自己APPID
  16. 如何使用jquery修改css中带有!important的样式属性
  17. 财富:保罗·艾伦转向新领域
  18. Oracle EBS 开发如何获得并发请求REQUEST ID
  19. matlab计算涡度的函数_涡度的计算
  20. mysql检测不到运行库_请自行检查是否安装VC9运行库??

热门文章

  1. 若个人计算机主板上的内存条松动,电脑内存条松动了怎么办?
  2. python turtle画四叶草的步骤_用Python的turtle作画(1)——花树
  3. c语言数组初始化的区别
  4. 删除数组中指定的值的方法
  5. Oracle数据结构和指令
  6. 【华为Mate10】缓解手机自带存储空间压力可以转到SD的内容
  7. 【深度策略研究文章】《 浅析金融帝国实验室Capitalism Lab中的商品运费和物流机制》(作者:jiuliumuliao)
  8. 儿童鞋里藏剪刀?回力鞋加紧线上品牌打假
  9. SSM酒店预约管理系统 计算机毕业设计源码40970
  10. NFT 游戏互操作性:技术不是拦路虎