va_start, va_arg, va_end 相关

va_list(),va_start(),va_arg(),va_end() 详细解析 些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件.下面我们写一个简单的可变参数的函数,该函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值 立即下载

本文主要介绍va_start和va_end的使用及原理。
核心思想:只是参数个数可变,但参数的类型可知,用format指出参数是什么类型。

函数原型如下:

#include <stdarg.h>

void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);

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

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

这种方式和我们以前认识的不大一样,但我们要记住这是C中一种传参的形式,在后面我们就会用到它。

2、函数参数的传递原理

函数参数是以栈的形式存取:如func(x,y,z,…)中的参数从右至左入栈。

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

栈底(物理高地址)栈顶(物理低地址)
栈中已有内容可变参数 …zyx

stdarg.h 重要的宏定义

typedef char* va_list;
va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。

void va_start ( va_list ap, prev_param ); /* ANSI version */
功能:让ap指针指向第一个可变参数prev_param 的地址

type va_arg ( va_list ap, type );
功能:让ap指针根据可变参的地址和可变参的类型取出一定长度内存里的数据(如int类型是4字节)

void va_end ( va_list ap );

取参步骤:
1、在调用参数表之前,定义一个 va_list 类型的变量,(假设va_list类型变量被定义为ap);
2、对ap 进行初始化,让它指向可变参数表里面的第一个参数,这是通过va_start 来实现。va_start 第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即 “ … ” 之前的那个参数(Z);
3、获取参数,调用 va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回变参表中这个指定类型的值,并且把ap 的位置指向变参表的下一个变量位置;当变参表中的所有参数都获取完毕时,此函数会返回 NULL。
4、获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end,他是输入的参数ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。说白了,就是让我们的程序具有健壮性。通常va_start和va_end是成对出现。

3、例程

  • 1
#include 〈stdio.h〉
#include 〈string.h〉
#include 〈stdarg.h〉

/* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号 */
int demo( char*, ... );

int main(int argc, char** argv )
{
	/* 
	 * 注意第一个参数 “DEMO”,不属于变参列表中的参数,
	 * 不能够被 va_arg 函数获取。
	 */
   demo("DEMO", "This", "is","a", "demo!", "");
   return 0;
}


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*); 
        /* 一个一个取出可变参数,直到 para 为 NULL,
         * 表明所有的可变参数均已获取到。
         */
        if (NULL == para) // va_arg( argp, char);一个一个字符char取出可变参数,直到碰到空字符串‘’‘’
			break;
        printf("Parameter #%d is: %s\n", argno, para);
        argno++;
    }
    /*将argp置为NULL*/
	va_end( argp );
	return 0;
}

输出:
(注意例程中第一个参数 “Demo” 不属于可变参数列表,因此不会输出)

Parameter #0 is: This
Parameter #1 is: is
Parameter #2 is: a
Parameter #3 is: demo

  • 2
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include <stdarg.h>

void log_to_console(char *format,...) {
	va_list args;
	va_start(args,format);
	vfprintf(stdout,format,args);

	va_end(args);
	fprintf(stdout,"\n");
	fflush(stdout);
}

int main(int argc, char** argv)
{

	log_to_console("%s, %d, %c", "hello", 22, '6');
	return 0;
}

几种负载均衡策略(DNS、NAT、重定向、反向代理) 摘要:本文对比了四种负载均衡技术:DNS负载均衡通过域名解析分发IP,用户直连服务器;NAT负载均衡通过VIP转发流量,所有流量经过负载均衡器;HTTP重定向通过302跳转实现分流;反向代理则隐藏后端服务器,统一转发请求。DNS简单但调度不精准,NAT精准但有带宽瓶颈,HTTP重定向延迟高,反向代理性能好但需专用设备。适用场景各异,DNS适合异地分流,NAT适合内网集群,HTTP重定向适合简单分流,反向代理适合高并发场景。核心区别在于层级(3层/7层)和流量走向(直连/中转)。 阅读详情

相关推荐

【Cadence】stb仿真和ac仿真——以一个简单的全差分反相放大器仿真为例

最近在补一些仿真方法学的问题,以及一些一直以来都有点模糊的概念,简单记录一下。搭建一个以两个CMOS反相器构成的全差分放大器(28nm工艺,PMOS和NMOS尺寸一致)激励的设置方便共模和差模仿真用同一个TB(这里有一个问题:这个放大器需要在开环下仿真还是闭环下?哪些放大器应用在开环,哪些闭环?这种应用场景不同会导致需要仿真得到开环还是闭环增益,或者环路增益?(我知道放大器在设计的时候肯定都是闭环应用的多,但是什么时候没必要闭环应用?光验证ac和stb仿真是否一样的话有必要有回路吗?

weixin_44951108的博客 5万+

数学中常见的arg min,arg max是什么意思

arg    是变元(即自变量argument)的英文缩写。 arg min 就是使后面这个式子达到最小值时的变量的取值 arg max 就是使后面这个式子达到最大值时的变量的取值 例如 函数F(x,y): arg  min F(x,y)就是指当F(x,y)取得最小值时,变量x,y的取值 arg  max F(x,y)就是指当F(x,y)取得最大值时,变量x,y的取值

JayMining的博客 24万+

Kubernetes集群资源优化实战:Volcano调度器如何帮你省下30%GPU算力

本文详细介绍了如何通过Volcano调度器的Binpack策略优化Kubernetes集群中的GPU资源利用率,解决AI模型训练中的资源碎片化问题。通过实战配置和调优指南,帮助用户提升30%的GPU算力利用率,显著降低任务等待时间和硬件成本。

weixin_30832143的博客 506

C语言函数之可变参数原理:va_start、va_arg及va_end

说到C语言函数可变参数,我们最先想到的可能就是printf、scanf、printk了。在Linux-2.6.24.7内核源码里,printk函数原型如下: asmlinkageintprintk(constchar*fmt,...) asmlinkage表示通过堆栈传递参数。gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定...

stephenbruce的博客 9254

旋转因子量化仿真

在单bit接收机中,通过量化FFT核函数来简化计算,将复数坐标中旋转因子单位圆上的点近似到正方形四个边上,就能够用累加实现复数乘法,从而避免使用DSP乘法器。通过仿真查看不同阶的核函数简化效果。

CyberInversion的博客 3102

基于Super-Jacoco的精准测试实践之路

灵魂拷问这个版本的影响范围到底有多大?研发改动了代码,为什么不通知测试?测试用例真的全面覆盖了吗?测试同学的测试覆盖情况该怎么评估?什么是精准测试概念借助技术手段、通过辅助算法对软件测试过...

咻咻ing的专栏 5837

可变参数:va_list(),va_start(),va_arg(),va_end() 详细解析

与 printf 类似,vsnprintf 可以根据格式化字符串中的占位符,将后续参数转换成对应的字符串并输出到缓冲区中,但是与 printf 不同的是,vsnprintf 可以指定输出的最大长度,以避免缓冲区溢出的问题。(1)format函数是一个可变参数函数,第一个参数pFmt是一个格式化字符串,后面的参数可以是任意数量的参数,用于填充格式化字符串中的占位符。va_start宏需要两个参数,分别是一个va_list类型的变量和可变参数的最后一个固定参数的地址。对变长参数列表进行访问和操作。

bigger_belief的博客 1万+

智能体异常行为检测-基于行为序列的异常模式识别技术【附代码】

在多智能体系统(Multi-Agent Systems, MAS)中,智能体之间的行为协调与自主决策是系统稳定运行的关键。然而,当某个智能体因策略偏移、环境变化或潜在攻击而出现**异常行为(Abnormal Behavior)**时,整个系统可能陷入混乱或崩溃。

一键难忘的博客 1142

C语言可变参数 va_start, va_arg, va_end使用介绍

我们常用的打印函数printf就是一个可变参数的函数,参数个数并不是固定的,函数原型为: int printf(const char *format, ...); 这就是一个典型的变参函数,其中的变参用三个点 ... 表示。 那么该如何编写自己的变参函数呢,这就要用到处理变参的三个方法:va_start, va_arg, va_end , 这三个方法包含在头文件 stdarg.h 中,这三个

zhang197093的博客 3828

Autosar CAN 网络管理标准文档

Autosar CAN 网络管理标准文档

蚂蚁小兵 923

解决pd.read_json报错ValueError: Trailing data问题

首先,我们使用open函数打开JSON文件,然后使用json.load函数将JSON文件数据解码为Python对象。在使用Python进行数据处理中,我们经常需要将JSON格式的数据读入到DataFrame中进行处理。而使用pandas库的read_json函数,就可以方便地将JSON数据读入到DataFrame中。但是有时候在读取JSON数据时,会遇到一个非常常见的错误:ValueError: Trailing data。这个错误的解决方案并不难,只需要在read_json中添加一个参数即可。

学习使你进步。 2234

Python基础知识点——简单 函数

前言 到目前为止,我们的 Python 代码已经实现了小的分块。它们都适合处理微小任务,但是我们想复用这些代码,所以需要把大型代码组织成可管理的代码段。代码复用的第一步是使用函数,它是命名的用于区分的代码段。函数可以接受任何数字或者其他类型的输入作为参数,并且返回数字或者其他类型的结果。 简单函数 函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤: 定义函数——封装独立的功能 调用函数——享受封装的成果 函数的作用,在...

Python案例分享,B站视频教程:https://space.bilibili.com/523606542 2459

【深度学习新浪潮】算力上太空:NVIDIA Space-1 Vera Rubin Module 深度技术解析

NVIDIA Space-1 Vera Rubin Module 不只是一款芯片模组,它是天地一体化 AI 的基础设施底座。它用成熟的 GPU 架构 + 航天级加固,把地面 AI 生态直接平移到太空。下一个 AI 创新战场,不在云端,而在轨道。在轨 LLM星上多模态实时处理卫星自主组网与分布式推理太空算力成为云计算的一级节点参考资料NVIDIA 官方博客:NVIDIA 推出太空计算,将 AI 送入太空轨道GTC 2026 黄仁勋主题演讲。

专注:太空算力、AI infra、异构调度、大模型成本工程 1124

va_list 、va_start、va_arg 和 va_end的含义和用法

这些宏提供了一种在函数中处理可变数量参数的方式,通常用于实现变参函数(variadic functions)。是一个类型,通常是一个指向可变参数列表的指针。你可以使用它来访问可变参数的内容。是C/C++中用于处理可变参数的一种机制,通常与相关的宏一起使用,如。宏用于结束对可变参数的访问,并且通常放在函数的最后。宏用于从可变参数列表中获取参数的值。和相关宏来接受可变数量的整数参数,然后计算它们的总和。对象,第二个是要获取的参数的类型。对象,第二个是最后一个非可变参数。,你可以逐个获取可变参数的值。

qq_38409301的博客 1093

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

va_list/va_start/va_end/va_arg、printf的实现及其家族

1.va_list等 先了解一下调用函数时,实参入栈的方式 stdarg.h中的定义 #inclde<stdarg.h> typedef char *va_list; #define va_start(list,param1) ( list = (va_list)&param1+ sizeof(param1) ) #define va_arg(list,mode) (...

qq_22655017的博客 441

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

va_list 、va_start、 va_arg、 va_end实例解析

qq_36412526的博客 503

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

va_list va_start va_arg va_end

vsnprintf函数 头文件:#include <stdarg.h> 函数原型:int vsnprintf(char *str, size_tsize, const char *format, va_listap); 函数说明:将可变参数格式化输出到一个字符数组 参数: str输出到的数组,size指定大小,防止越界,format格式化参数,ap可变参数列表函数用法 #incl...

chenliang0224的专栏 196

va_start() - va_end() - va_arg() - va_copy() - va_list - Handle variable argument list (处理可变参数列表)

va_start() - va_end() - va_arg() - va_copy() - va_list - Handle variable argument list (处理可变参数列表)

程永强 1158

va_list va_arg va_start va_end 这些宏定义的使用, c 语言的可变参函数;函数的调用约定;

(1) 先给出测试的例子,已经编译通过;

zhangzhangkeji的博客 238

C语言 - 可变参数函数 va_list、va_start、va_arg、va_end

C语言可变参数函数介绍

hinewcc的博客 877

Va_list以及相关函数的使用方法。

Va_list以及相关函数的使用方法。 在头文件stdarg.h里面找到了关于这个几个函数的宏定义 #if  !defined(__STDARG) #define __STDARG typedef void    *va_list; #define va_start(ap, parmN)   (ap = ...) #define va_arg(ap, type) (*((type *)(...

qq_40057863的博客 371

Arch64中va_list/va_start/va_arg/...的实现

可变参函数指的是一个可以接受可变个参数的函数

weixin_39094034的博客 574

C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数

在定义可变参数的函数之前,先来理解一下函数参数的传递原理:

技术改变生活 6216

va_list,va_start,va_end,va_copy,vprintf,vfprintf,vsprintf,vsnprintf

#include        int printf(const char *format, ...);        int fprintf(FILE *stream, const char *format, ...);        int sprintf(char *str, const char *format, ...);        int snprintf(char

安子自语 1585

va_start和va_end使用详解

本文主要介绍va_start和va_end的使用及原理。   在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end这两个宏,但对它们也只是泛泛的了解。   介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理:  1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 void foo(

Dosth_Magic 633

C++基础-va_list的使用

va_list定义于头文件中,是用于处理C语言风格变参函数而使用的一种对象类型,va_list类型的变量是指向参数的指针,通过指针运算来调整访问的对象,其主要使用如下几种宏来进行操作.

qq_73143395的博客 1151
上一篇: 59 linux lcd驱动
下一篇: 60 rtc 实时时钟驱动
你板子冒烟了
博客等级 码龄8年 1278粉丝 582原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值