va_start 与 va_end用法

2023-05-16


1. 包含头文件:     

        #include <stdarg.h>

2.使用方法

      参考:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
//WIN7 64BIT
#define PLAT_ADDRESS_SIZE 8
/*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,"\n")==0)break; 
		printf("Parameter #%d addr=0x%x is: %s\n", argno,para, para); 
		argno++; 
	} 
	va_end( argp ); 
	/*将argp置为NULL*/
	return 0; 
}
int test_for_stack(int num, ...)  
{  
    int i, result = 0;  
  	char *pitmp; 
    va_list ap;//这里写的什么list,(搞得好像是得到可变参数列表头一样)其实它就是个字符指针:char * 
	  
    va_start(ap, num);// 这里把上面得到的字符指针,后移动4个字节,就是跳过num的内存地址  
    printf("num:%d, *ap:%d\n", num, *ap);// 这里打印下就会看出,*ap 跳过了num指向了下一个参数  
    
	pitmp = ap; 
    for (i = 0; i < num; i++)//这里num表示可变参数列表中有多少个参数(num本身算不算,由自己觉得,这里是不算入参数个数的)  
    {     
        result = va_arg(ap, int);//这里把ap往后跳过4个字节(sizeof(int)大小)指向下一个参数,返回的是当前参数(而非下一个参数)  
        printf("in for  result:%d,  *ap:%d\n", result, *ap);//这里打印下,可以看出,ap总是指向result后面的那个参数  
    }     
    va_end(ap); 
  
    return result;  
} 



/*测试可变参数*/ 
int test_for_stack_address(int num, ...)  
{  
    int i, result = 0;  
  	char *ptmp; 
    va_list ap;//这里写的什么list,(搞得好像是得到可变参数列表头一样)其实它就是个字符指针:char * 
	  
    va_start(ap, num);// 这里把上面得到的字符指针,后移动4个字节,就是跳过num的内存地址  
  	
	  /*固定参数地址 & 值*/
      printf("fixed parameter value:%d,address:0x%x\n", num, ap-PLAT_ADDRESS_SIZE);
    printf("parameter num:%d, *ap:%d\n", num, *ap);
    
	ptmp = ap; 
    for (i = 0; i < num; i++) 
    { 
		printf("#%d --> stack addr:0x%x,  *pitmp:%d\n",i, ptmp, *ptmp);  
        ptmp += PLAT_ADDRESS_SIZE;
    }     
    va_end(ap);
  
    return result;  
} 

/*
1.函数栈的生长方向 
		
	1.1 测试结果1 (测试平台:WIN7 64BIT DEV-CPP)
		<-高内存地址处 
		|---------------------------------| 
		|   最后一个可变参数              |    
		|---------------------------------| 
		|---------------------------------| 
		|   第N个可变参数                 |     -> va_arg(arg_ptr,int)后arg_ptr所指的地方, 即第N个可变参数的地址。 
		         
		|   第一个可变参数                |     -> va_start(arg_ptr,start)后arg_ptr所指的地方  即第一个可变参数的地址 
		
		|   最后一个固定参数              |     -> start的起始地址 
		|---------------------------------|
		|---------------------------------|     -> 第 N个固定参数     
		<-低内存地址处
		
		*调用test_for_stack_address(4,10,20,30,40)的运行结果: 		
			*************test_for_stack_address*************
			cpu address length -> int * = 8
			cpu address length -> char * = 8
			
			fixed parameter value:4,address:0x22fe10
			parameter num:4, *ap:10
			#0 --> stack addr:0x22fe18,  *pitmp:10
			#1 --> stack addr:0x22fe20,  *pitmp:20
			#2 --> stack addr:0x22fe28,  *pitmp:30
			#3 --> stack addr:0x22fe30,  *pitmp:40
2.参数的入栈顺序 
3.CPU的对齐方式 
4.内存地址的表达方式 
*/


int table[10]={1};
int main()
{
	printf("\r\n*************test_for_table_address*************\r\n");
	printf("table[0] address = 0x%x\r\n",&table[0]);
	printf("table[1] address = 0x%x\r\n",&table[1]);
		
	printf("\r\n*************test_for_stack_address*************\r\n");
	printf("cpu address length -> int * = %d\r\n",sizeof(int *));
	printf("cpu address length -> char * = %d\r\n",sizeof(char *));
	printf("\r\n");

	test_for_stack_address(4,10,20,30,40);  
	
	test_for_stack(4,10,20,30,40); 
	demo("DEMO", "This", "is", "a", "demo!" ,"333333", "\n");
	
	while(1);
	return 0;
}







3.具体应用

    a.类似printf的用法(UART)

static char stdio_msg_buf_[MAX_MSG_LEN];
int printf(const char *format, ...)
{
	va_list args;
	uint32_t ret,len;
	/* Format the string */
	/*在这儿添加 get 信号量、自旋锁*/
        ........
	va_start(args, format);
	vsnprintf(stdio_msg_buf_, MAX_MSG_LEN, &format[0], args);
	va_end(args);
	
	len= strlen(stdio_msg_buf_);             /*计算字符长度*/
 ret=write_to_uart(stdio_msg_buf_, len);
	/*在这儿添加 realese 信号量、自旋锁*/
 .........return ret;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

va_start 与 va_end用法 的相关文章

随机推荐

  • 程序猿代码面试指南 PDF

    前言 今年是最难求职年 xff0c 我希望通过这篇文章能帮大家提高求职成功率 这篇文章分为简历篇 面试篇 谈薪酬篇 xff0c 包括了找工作过程中各个环节的技巧和防坑指南 这篇文章就是给大家分享左神这本 程序员代码面试指南 IT名企算法与数
  • 从 Java 代码逆向工程生成 UML 类图和序列图

    前言 本文面向于那些软件架构师 xff0c 设计师和开发人员 xff0c 他们想使用 IBM Rational Software Architect 从 Java 源代码来逆向工程生成 UML 类和序列图 逆向工程经常被用来从已有的源代码中
  • http的三次握手

    在http的三次握手当中 xff0c 首先客户端发起一个我要发送一个数据包的请求 xff0c 发送到服务端 xff0c 这里面呢会有一个标志SYN 61 1 Seq 61 X xff0c syn是一个标识 xff0c 就是我这是一个创建请求
  • SQL优化面试专题

    介绍 xff1a 无论您是创建Web应用程序的开发人员 xff0c 还是参与Web测试的DBA或测试人员 xff0c SQL方面的技巧在数据库编程和数据库验证中都非常重要 因此 xff0c 我们整理了QL性能优化方面的面试问题 SQL性能优
  • Docker容器:将带UI的程序直接转为Web应用,so easy

    摘要 xff1a 使用Docker容器 xff0c 将带UI的程序 xff0c 直接转换为Web应用 很方便 xff0c 跟大家分享一下 本文分享自华为云社区 使用Docker容器 xff0c 将带UI的程序 xff0c 直接转为Web应用
  • 38道多线程核心面试题(附答案)

    前言 今天给大家分享的是比较全面的多线程面试题 xff0c 大家在面试的过程中不免会被问到很多专业性的问题 xff0c 有的时候回答的并不是那么全面和精细 xff0c 这仅仅代表个人观点 1 如何预防死锁 xff1f 1 首先需要将死锁发生
  • Java程序员,最常用的20%技术有哪些?

    1 基本的数据结构和算法真的非常重要 xff1a 不管你做过多少项目或者是熟悉多少框架和工具 xff0c 面试和考察一个人还是大部分停留在基本功上 所以 xff0c 在每天工作开发之余 xff0c 应保证一定的时间段不断去打磨自己的基本功
  • Linux 程序编译过程详解

    大家肯定都知道计算机程序设计语言通常分为机器语言 汇编语言和高级语言三类 高级语言需要通过翻译成机器语言才能执行 xff0c 而翻译的方式分为两种 xff0c 一种是编译型 xff0c 另一种是解释型 xff0c 因此我们基本上将高级语言分
  • 关于485总线 A、B端上拉下拉电阻选择

    问 xff1a about rs485 用电阻上拉 B用电阻下拉 A B间用电阻连接 xff0c 这些电阻参数大致多少 xff1f 我们公司的设计是 TTL输入都用光偶隔离 输出加上拉和下拉 xff0c 中间加TVS和2个电阻串联 xff0
  • JAVA集合框架(一)-ARRAYLIST

    1 ArrayList的特点 存放的元素有序元素不唯一 可以重复 随机访问快插入删除元素慢非线程安全 2 底层实现 底层初始化 xff0c 使用一个Object类型的空对象数组 xff0c 初始长度为0 源码 Object类型对象数组引用
  • Java如何将两个数组合并为一个数组呢?

    数组 xff1a 数组 xff08 Array xff09 是有序的元素序列 1 若将有限个类型相同的变量的集合命名 xff0c 那么这个名称为数组名 组成数组的各个变量称为数组的分量 xff0c 也称为数组的元素 xff0c 有时也称为下
  • pca9548及vsc9548的设备树简单挂载

    简述 pca9548及vsc9548是iic拓展器件 xff0c 主要是防止iic器件地址冲突 通过写其0x0寄存器可切换0 7路iic 设备树挂载 这里用到了vsc9548 xff0c 且在第7路上挂在了eeprom器件 i2c 64 f
  • 类的作用域

    类的作用域简称类域 xff0c 它是指在类的定义中由一对花括号所括起来的部分 每一个类都具有该类的类域 xff0c 该类的成员局部于该类所属的类域中 在类的定义中可知 xff0c 类域中可以定义变量 xff0c 也可以定义函数 从这一点上看
  • 常见问题(持续更新)

    近期整理的初级开发遇到的问题 xff0c 希望对大家有用 1 Unsatisfied dependency expressed through field 39 baseMapper 39 于是在pom xml中搜索mybatis关键字 x
  • orb-slam中的orb特征

    1 ORB特征简介 ORB是Oriented FAST and Rotated BRIEF xff08 oFAST and rBRIEF xff09 的简称 xff0c ORB的名字已经说明了其来源 xff0c 其实ORB特征是采用FAST
  • 计算机组成原理 第二篇:总线 1.总线原理和意义

    总线是什么 总线是连接多个部件的信息传输线 是各部件共享的传输介质 总线可以传输的原理 总线实际上是由许多传输线或通路组成 每条线上保持的电平高低即是所传输的信号 每条线可一位一位地传输二进制代码 一串二进制代码可以在一段时间内逐一传输完成
  • 主流深度学习算法简介

    深度学习算法简介 1 深度学习主流算法包括 1 1 CNN 卷积神经网络 卷积神经网络 xff08 CNN xff09 是最常见的深度学习方法之 一 自20 世纪80 年代后期以来 xff0c CNN 已应用于视觉识别与分类任务 xff0c
  • 常见外贸英文术语(下)

    很多从事外贸行业的人都会用Skype IntBell AntTone等网络电话和客户沟通 xff0c 但是有时候会因为一些外贸行业的专业英文术语闹出笑话 今天就让我们来总结一些外贸常见英文术语 xff0c 让你和客户沟通更加顺畅 xff01
  • Phpstorm2018 使用破解补丁永久激活

    1 安装phpstorm xff0c 安装包请自行官网下载 http www jetbrains com phpstorm download 2 下载JetbrainsCrack jar文件 xff0c 存放至你的phpstorm执行文件同
  • va_start 与 va_end用法

    1 包含头文件 include lt stdarg h gt 2 使用方法 参考 http www cnblogs com hanyonglu archive 2011 05 07 2039916 html include lt stdio