(const char *format, ...) 可变参数在文本日志中的巧妙使用

1. va_list是C语言中的一个数据类型,用于处理可变参数列表。它通常与stdarg.h头文件一起使用,该头文件提供了一组宏和函数来处理可变参数。

va_list类型用于存储一系列类型未知的参数,这些参数可以是任意类型,包括整数、浮点数、字符和指针等。它是一个结构体类型,通常在实现可变参数函数时定义。

使用va_list和相关的宏,可以实现在函数调用时动态地指定参数的数量和类型。这使得函数能够接受可变数量的参数,并且能够处理不同类型的参数。这种机制使得在函数定义时无需预先指定参数的类型和数量,提供了更大的灵活性和便利性。

2. va_start的实现方式是依赖于具体的编译器和平台的。在大多数情况下,va_start的实现是编译器相关的,并依赖于平台上的寄存器或者其他机制来传递参数。

在大多数情况下,编译器会将可变参数列表存储在内存中的某个位置,然后使用特定的寄存器或者指针来引用该位置。va_start的作用就是初始化这个寄存器或者指针,以便后续的va_arg宏可以正确地获取参数。

具体来说,va_start会执行以下操作:

  1. 确定可变参数列表的起始位置。这个位置通常是由函数调用约定确定的,例如在C语言中,可变参数列表通常存储在栈帧中的某个特定位置。
  2. 初始化一个va_list类型的变量,该变量用于存储参数列表的当前位置。这个变量通常是一个结构体或者一组寄存器,具体取决于编译器和平台。
  3. 设置参数列表的初始位置,以便后续的va_arg宏可以正确地获取参数。这通常涉及到将参数列表的起始位置和当前位置信息存储到va_list类型的变量中。

一旦va_start被调用,就可以使用va_arg宏从参数列表中获取参数,直到所有参数都被获取完毕。最后,需要调用va_end宏来清理参数列表相关的资源。

3. va_arg() 用于从可变参数列表中获取一个参数。va_arg() 宏接受两个参数:va_list 类型的变量和一个类型。它会将可变参数列表中的下一个参数转换为一个指向给定类型的指针,并返回该指针的值。例:

void print_numbers(int n, ...) {  
    va_list args;  
    va_start(args, n);  
  
    for (int i = 0; i < n; i++) {  
        int value = va_arg(args, int);  
        printf("%d ", value);  
    }  
  
    va_end(args);  
}  

4. va_end()是一个宏,用于清理使用va_start()宏开始的可变参数列表。例如在函数接受可变数量的参数时,需要使用va_start()宏来开始参数列表,然后使用va_arg()宏来获取参数。一旦处理完所有参数,应该使用va_end()宏来清理参数列表。

va_end()宏会释放由va_start()宏分配的内存,并确保参数列表正确终止。如果不调用va_end()宏,可能会导致内存泄漏或其他问题。

5. 通过可变参数函数我们可以实现类似于printf函数的日志上报函数:

/// @brief 添加带数据的日志内容
/// @param format
/// @param
void model_log_add_data(const char *format, ...)
{
	// return_if_fail(stModel_log_page.inited == 1);
	OS_ERR err;
	OSMutexPend(&stModel_log_page.mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err);

	va_list args;
	va_start(args, format);

	static char buffer[256];
	vsnprintf(buffer, sizeof(buffer), format, args);
	buffer[sizeof(buffer) - 1] = '\0';
	int len = strlen(buffer);

	return_if_fail(len < MODEL_LOG_DATA_LEN);

	if (stModel_log_page.len + len > MODEL_LOG_DATA_LEN)
	{
		model_log_report();
		model_log_data_init();
	}

	strcat(stModel_log_page.data, buffer);
	// printf("%s\r\n", stModel_log_page.data);
	stModel_log_page.len += len;

	va_end(args);

	OSMutexPost(&stModel_log_page.mutex, OS_OPT_PEND_BLOCKING, &err);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/126426.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法之路(一)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 :算法小能手 &#x1f606;今日分享 : 如何学习&#xff1f; 在学习的过程中&#xff0c;不仅要知道如何学习&#xff0c;还要知道避免学习的陷阱。1. 睡眠不足&#xff1b;2. 被动学习和重读&#xff1b;3. 强调标记或画线&am…

基于讯飞星火大语言模型开发的智能插件:小策问答

星火大语言模型是一种基于深度学习的自然语言处理技术&#xff0c;它能够理解和生成人类语言。这种模型的训练过程涉及到大量的数据和复杂的算法&#xff0c;但最终的目标是让机器能够像人一样理解和使用语言。 小策问答是一款基于星火大语言模型的定制化GPT插件小工具。它的主…

电脑硬盘数据恢复哪个好?值得考虑的 8 个硬盘恢复软件解决方案

借助硬盘恢复软件&#xff0c;任何人都可以在家中恢复丢失的文件&#xff0c;而无需任何特殊技能。事实上&#xff0c;最困难的一步是选择最佳解决方案&#xff0c;因为可用选项的数量可能有点多。幸运的是&#xff0c;这篇文章可以为您提供帮助。 8 款顶级硬盘数据恢复软件解决…

Spring Cloud和Kubernetes + Spring Boot 用哪个?

Spring Cloud和Kubernetes Spring Boot都是用于构建微服务架构的解决方案&#xff0c;它们各有优势和不足&#xff0c;选择哪个更好取决于你的具体需求和上下文。 Spring Cloud是一个基于Spring Boot的微服务开发框架&#xff0c;它提供了一套完整的微服务解决方案&#xff0…

【Java】I/O流—缓冲流的基础入门和文件拷贝的实战应用

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;你能坚持到什么程度&#xff0c;决定你能达到什么高度 &#x1f4e2;欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 文章目录 一.&…

2023.11.7 Spring 依赖注入的三大方式

目录 前言 属性注入&#xff08;Autowired&#xff09; Setter 注入 构造方法注入 Resource Autowired 和 Resource 的区别 Autowired 和 Resource 查找 Bean 对象的区别 前言 配置文件 ​ <?xml version"1.0" encoding"UTF-8"?> <beans …

kafka微服务学习

消息中间件对比&#xff1a; 1、吞吐、可靠性、性能 Kafka安装 Kafka对于zookeeper是强依赖&#xff0c;保存kafka相关的节点数据&#xff0c;所以安装Kafka之前必须先安装zookeeper Docker安装zookeeper 下载镜像&#xff1a; docker pull zookeeper:3.4.14创建容器 do…

【Redis缓存架构实战常见问题剖析】

文章目录 一、Redis缓存架构实战剖析1.1、大规模的商品缓存数据冷热分离机制1.2、缓存击穿导致线上数据压力暴增解决方案1.3、缓存穿透及其解决方案剖析1.4、突发性的热点缓存数重建导致系统压力暴增问题分析1.5、Redis分布式锁解决缓存与数据库双写不一致问题剖析1.6、利用多级…

Python机器学习算法入门教程(第四部分)

接着Python机器学习算法入门教程&#xff08;第三部分&#xff09;&#xff0c;继续展开描述。 十九、信息熵是什么 通过前两节的学习&#xff0c;我们对于决策树算法有了大体的认识&#xff0c;本节我们将从数学角度解析如何选择合适的“特征做为判别条件”&#xff0c;这里…

微服务 Spring Cloud 5,一图说透Spring Cloud微服务架构

目录 一、域名系统DNS二、LVS&#xff08;Linux Virtual Server&#xff09;,Linux虚拟服务器三、CDN静态资源四、Nginx反向代理服务器1、Nginx的主要作用体现在以下几个方面&#xff1a;2、Nginx静态资源服务和CDN静态资源服务&#xff0c;如何选择&#xff1f; 五、Gateway网…

C#上位机序列10: Winform上位机通用框架

C#上位机序列1: 多线程&#xff08;线程同步&#xff0c;事件触发&#xff0c;信号量&#xff0c;互斥锁&#xff0c;共享内存&#xff0c;消息队列&#xff09; C#上位机序列2: 同步异步(async、await) C#上位机序列3: 流程控制&#xff08;串行&#xff0c;并行&#xff0c…

Panorama SCADA平台的警报通知功能配置详解

1. 前言 SCADA系统的主要目标是采集与监控工业过程数据&#xff0c;以确保工业生产正常运行。通过实时警报通知功能&#xff0c;操作人员可以立即获取有关潜在问题的信息&#xff0c;从而能够快速采取行动解决问题&#xff0c;防止进一步的损害或生产中断。因此&#xff0c;及…

三相电机的某些实测特性曲线

三相电机参数&#xff1a; 0.75KW&#xff0c;额定电流是2A&#xff0c;功率因数0.71&#xff0c;效率78.9%。制式S1. 1.负载不变时的线电压与线电流的关系 1.1相关数据与python代码&#xff1a; 这里记录了一系列的实验&#xff1a; 第一组实验&#xff1a;近乎空载&#xf…

企业微信开启接收消息+验证URL有效性

企业微信开启接收消息验证URL有效性 &#x1f4d4; 千寻简笔记介绍 千寻简笔记已开源&#xff0c;Gitee与GitHub搜索chihiro-notes&#xff0c;包含笔记源文件.md&#xff0c;以及PDF版本方便阅读&#xff0c;且是用了精美主题&#xff0c;阅读体验更佳&#xff0c;如果文章对…

[Framework] Android Handler 工作原理

作者&#xff1a;Tans5 Android 中的 Handler 都被人说烂了&#xff0c;但是还是想多说一次&#xff0c;因为在 Android 的系统中它真的非常重要而且它的机制并没有很复杂&#xff0c;无论是新手和老手都可以好好学习下&#xff0c;这对理解 Android 系统很重要&#xff0c;所以…

如何进行网站测试

随着市场和技术的快速发展&#xff0c;产品需要不断更新和改进以保持竞争力&#xff0c;如果产品停滞不前&#xff0c;很可能会被市场淘汰。通过持续发展&#xff0c;企业可以不断优化产品&#xff0c;提高用户体验&#xff0c;从而赢得市场份额和客户忠诚度。而数通在激烈的市…

计算机毕业设计项目选题推荐(免费领源码)Java+springboot+Mysql停车微信小程序小程序92714

摘 要 在信息飞速发展的今天&#xff0c;网络已成为人们重要的信息交流平台。每天都有大量的农产品需要通过网络发布&#xff0c;为此&#xff0c;本人开发了一个基于springboot停车微信小程序小程序。 对于本停车微信小程序的设计来说&#xff0c;它主要是采用后台采用java语…

Vue+OpenLayers 创建地图并显示鼠标所在经纬度

1、效果 2、创建地图 本文用的是高德地图 页面 <div class"map" id"map"></div><div id"mouse-position" class"position_coordinate"></div>初始化地图 var gaodeLayer new TileLayer({title: "高德地…

PDF有限制密码,不能复制怎么办?

大家现在接触PDF文件越来越多&#xff0c;有的时候在网上下载的PDF文件打开之后&#xff0c;发现选中文字之后无法复制。甚至其他功能也都无法使用&#xff0c;这是怎么回事&#xff1f;该怎么办&#xff1f; 当我们发现文件打开之后&#xff0c;编辑功能无法使用&#xff0c;很…

数据库数据迁移常见方式

数据库数据迁移常见方式 数据库数据迁移常见方式1、通过sql2、通过数据迁移工具3、云服务进行数据迁移什么是DRS服务如何使用DRS服务DRS云服务可以干什么 数据库数据迁移常见方式 1、通过sql 批量导入sql insert into tableName select * 2、通过数据迁移工具 在数据库里面…