va_start,va_arg,va_end的使用
#include <stdio.h>
void fun(int n,...)
{
int *temp=&n;
temp++;
for(int i=;i<n;i++)
{
printf("%d\n",*temp);
temp++;
}
}
int main()
{
int a=,b=,c=,d=;
fun(,a,b,c,d);
return ;
}

二、使用va_start,va_arg,va_end
#include <stdio.h>
#include <stdarg.h>
void fun(int n,...) //变参函数,C++里也有
{
int temp,i;
va_list ap; //step1:va_list类型数据可以保存函数的所有参数,做为一个列表一样保存 va_start(ap,n); //step2:对ap 进行初始化,让ap指向可变参数表里面的第一个参数(最后一个固定参数后的可变参数)
for(i=;i<n;i++)
{
temp=va_arg(ap,int); //step3:把 ap 的位置指向变参表的下一个变量位置
printf("%d\n",temp);
}
va_end(ap); //step4:关闭ap指针
}
int main()
{
int a=,b=,c=,d=;
fun(,a,b,c,d);
return ;
}

⑴在intel+windows的机器上,函数栈的方向是向下的,栈顶指针的内存地址低于栈底指针,所以先进栈的数据是存放在内存的高地址处。
(2)在VC等绝大多数C编译器中,默认情况下,参数进栈的顺序是由右向左的,因此,参数进栈以后的内存模型如下图所示:最后一个固定参数的地址位于第一个可变参数之下,并且是连续存储的。
栈底 高地址
| .......
| 函数返回地址
| .......
| 函数最后一个参数
| ....
| 函数第一个可变参数 <--va_start后ap指向
| 函数最后一个固定参数
| 函数第一个固定参数
栈顶 低地址
因此,现在再来看va_arg()的实现就应该心中有数了:
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) -
_INTSIZEOF(t)) )
这个宏做了两个事情,
①ap指向下一个参数:ap +=
_INTSIZEOF(t)
_INTSIZEOF(t),然后在减去_INTSIZEOF(t),使得表达式结果为ap之前的值,即当前需要得到的参数的地址,强制转换成指向此参数的
int main(void)
{
int a=,b=;
b=((a+=)-);
printf("a:%d,b:%d\n",a,b);
b=((a+=)-);
printf("a:%d,b:%d",a,b);
return ;
}

va_start,va_arg,va_end的使用的更多相关文章
- va_list/va_start/va_arg/va_end深入分析【转】
转自:http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html va_list/va_start/va_arg/va_end ...
- C++省略参数(va_list va_start va_arg va_end)的简单应用
原文参考自:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html #include <iostream> #in ...
- va_list/va_start/va_arg/va_end深入分析
http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html
- va_start(),va_end()函数应用【转】
转自:http://www.cnblogs.com/gogly/articles/2416833.html 原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h&g ...
- va_start(),va_end()函数应用
原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下. VA_LIST的用法: (1)首先在函数里定义一具VA_LIST型的变 ...
- va_list、va_start和va_end使用
我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于1.硬件平台的不同 2.编译器的不同,所以定义的宏也有所不同. 在ANSI C中,这些宏的定义位于stdar ...
- va_start和va_end使用详解
本文主要介绍va_start和va_end的使用及原理. 介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理: 1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 ...
- [转载]va_start和va_end使用详解
va_start和va_end使用详解 原文地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_s ...
- [转载]C/C++可变参数之va_start和va_end使用详解
本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解. 介绍这两 ...
随机推荐
- Ionic APP-Web SPA开发进阶(一)AngularJS全栈工程狮进阶
AngularJS全栈工程狮进阶 前言 学习了一段时间AngularJS,开始接触移动端APP开发.为了响应公司开发需求,采用"Hybrid"混血开发方法.采用Ionic前端框架, ...
- 【Qt编程】Qt学习笔记<三>
1. 如果程序中使用了png以外格式的图片,在发布程序时就要将Qt安装目录下plugins中的imagineformats文件复制到发布文件中. 2. 在函数声明处快速添加函数定义 ...
- STL - queue(队列)
Queue简介 queue是队列容器,是一种"先进先出"的容器. queue是简单地装饰deque容器而成为另外的一种容器. #include <queue> queu ...
- sqlite相关使用
一.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能 ...
- mongodb系列之--mongodb 主从配置与说明
一.为什么要配置mongodb的主从: 1.做主从,可以说是做数据的备份,有利于故障的恢复 2.做主从,可以做到读写分离,主节点负责写操作,从节点负责读操作,这样就把读写压力分开,保证系统的稳定性. ...
- node.js 连接数据库
用Nodejs连接MySQL 用Nodejs连接MySQL 从零开始nodejs系列文章 ,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的 ...
- cdh5 hadoop redhat 本地仓库配置
cdh5 hadoop redhat 本地仓库配置 cdh5 在网站上的站点位置: http://archive-primary.cloudera.com/cdh5/redhat/6/x86_64/c ...
- iOS雷达图 iOS RadarChart实现
实现效果 刚拿到设计稿的时候大概看了一眼,当时心里想着放张背景图,然后计算下相应点的坐标,在最上面画一层就OK了,其实一开始实现的时候也确实是这么做的,然后我就日了狗了,发现设计稿上多层五边形的间隔不 ...
- hbase 集群管理脚本
#!/bin/bash # Show all running Java processes on region servers. Must run on master using HBase owne ...
- OpenCV——PS滤镜, 碎片特效
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...